Non Blocking Channel Operations in Cilk
Our example demonstrates non-blocking operations on channels using Cilk++. In Cilk++, we can use cilk::chan
for channel-like communication between tasks, and cilk_spawn
for creating concurrent tasks.
#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#include <cilk/reducer_opadd.h>
#include <cilk/cilk_io.h>
#include <iostream>
#include <string>
int main() {
cilk::chan<std::string> messages;
cilk::chan<bool> signals;
// Here's a non-blocking receive. If a value is
// available on `messages` then it will be received.
// If not, it will immediately take the else branch.
if (messages.try_recv()) {
std::string msg;
messages >> msg;
std::cout << "received message " << msg << std::endl;
} else {
std::cout << "no message received" << std::endl;
}
// A non-blocking send works similarly. Here `msg`
// cannot be sent to the `messages` channel if it's full,
// so the else branch is taken.
std::string msg = "hi";
if (messages.try_send(msg)) {
std::cout << "sent message " << msg << std::endl;
} else {
std::cout << "no message sent" << std::endl;
}
// We can use multiple try_recv operations to implement
// a multi-way non-blocking select. Here we attempt
// non-blocking receives on both `messages` and `signals`.
if (messages.try_recv()) {
std::string msg;
messages >> msg;
std::cout << "received message " << msg << std::endl;
} else if (signals.try_recv()) {
bool sig;
signals >> sig;
std::cout << "received signal " << sig << std::endl;
} else {
std::cout << "no activity" << std::endl;
}
return 0;
}
This code demonstrates non-blocking operations using Cilk++. While Cilk++ doesn’t have a direct equivalent to Go’s select
statement, we can achieve similar functionality using try_recv()
and try_send()
methods on cilk::chan
objects.
The program creates two channels: messages
for strings and signals
for booleans. It then performs three non-blocking operations:
- A non-blocking receive on
messages
. - A non-blocking send on
messages
. - A multi-way non-blocking receive on both
messages
andsignals
.
In each case, if the operation can be performed immediately, it is executed. If not, the program continues without blocking.
To run this program, you would compile it with a Cilk++ compatible compiler and then execute the resulting binary:
$ g++ -fcilkplus non_blocking_operations.cpp -o non_blocking_operations
$ ./non_blocking_operations
no message received
no message sent
no activity
This example showcases how to implement non-blocking channel operations in Cilk++, providing a way to handle concurrent communication without blocking the main execution flow.