Non Blocking Channel Operations in C++
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>
#include <atomic>
int main() {
std::vector<std::string> messages;
std::vector<bool> signals;
std::atomic<bool> messageReady(false);
std::atomic<bool> signalReady(false);
// Here's a non-blocking receive. If a value is
// available in `messages` then the if condition will be true
// and we'll process the message. If not, it will immediately
// take the else branch.
if (messageReady.load()) {
std::string msg = messages.back();
messages.pop_back();
std::cout << "received message " << msg << std::endl;
} else {
std::cout << "no message received" << std::endl;
}
// A non-blocking send works similarly. Here `msg`
// is added to the `messages` vector only if `messageReady`
// is false, simulating a non-blocking send.
std::string msg = "hi";
if (!messageReady.load()) {
messages.push_back(msg);
messageReady.store(true);
std::cout << "sent message " << msg << std::endl;
} else {
std::cout << "no message sent" << std::endl;
}
// We can use multiple conditions to implement a multi-way
// non-blocking select. Here we attempt non-blocking receives
// on both `messages` and `signals`.
if (messageReady.load()) {
std::string msg = messages.back();
messages.pop_back();
std::cout << "received message " << msg << std::endl;
} else if (signalReady.load()) {
bool sig = signals.back();
signals.pop_back();
std::cout << "received signal " << std::boolalpha << sig << std::endl;
} else {
std::cout << "no activity" << std::endl;
}
return 0;
}
This C++ code demonstrates non-blocking operations similar to the original example. However, C++ doesn’t have built-in channels or a select
statement like some other languages. Instead, we use std::vector
to simulate channels and std::atomic
variables to control access to these vectors in a thread-safe manner.
Here’s how the concepts are translated:
- Channels are simulated using
std::vector<std::string>
for messages andstd::vector<bool>
for signals. - Non-blocking operations are implemented using
std::atomic<bool>
flags (messageReady
andsignalReady
) to indicate whether a message or signal is available. - The
select
statement is replaced with a series ofif-else
conditions checking these atomic flags. - Sending a message is simulated by pushing to the vector and setting the corresponding atomic flag.
- Receiving a message is simulated by checking the atomic flag, and if true, popping from the vector.
This code provides a similar functionality to the original, demonstrating non-blocking operations in C++. However, it’s important to note that this is a simplified simulation and doesn’t provide all the guarantees and features of actual channel-based concurrency primitives.
To compile and run this program:
$ g++ -std=c++11 -pthread non_blocking_operations.cpp -o non_blocking_operations
$ ./non_blocking_operations
no message received
sent message hi
no activity
The output may vary depending on the timing of operations, which is expected in concurrent scenarios.