#include <thread>
#include <memory>
#include <random>
// SObjectizer is one of a few cross-platform and OpenSource "actor frameworks" for C++.
// But SObjectizer supports not only Actor Model, but also Publish-Subscribe Model and CSP-like channels.
// ver 5.7
#include <so_5/all.hpp>
// Message structure
struct poll_device_events_request_t { };
void thread_func(so_5::mchain_t primary_channel, so_5::mchain_t secondary_channel)
{
// The stuff necessary for random pause generation.
std::random_device rd;
std::mt19937 generator{rd()};
std::uniform_int_distribution<> pause_generator{5000, 10000}; // Delay between 5 - 10 seconds.
// This flag will be set to 'true' when some of channels will be closed.
bool stop = false;
auto prepared = so_5::prepare_select(
so_5::from_all().handle_all()
// If some channel gets closed we should set out 'stop' flag.
.on_close([&stop](const auto &) { stop = true; })
// A predicate for stopping select() function.
.stop_on([&stop]{ return stop; }),
// Read and handle poll_device_events_request messages from channel_.
so_5::receive_case(primary_channel,
[&](poll_device_events_request_t){
std::cout << "Received message on primary channel..." << std::endl;
// Do some work.
// Generate a random pause.
const std::chrono::milliseconds pause{pause_generator(generator)};
// Send a message to secondary channel - delayed message.
so_5::send_delayed<poll_device_events_request_t>(secondary_channel, pause);
}
),
so_5::receive_case(secondary_channel,
[&](poll_device_events_request_t){
std::cout << "Received message on secondary channel..." << std::endl;
// Do some work.
// Generate a random pause for processing of that request.
const std::chrono::milliseconds pause{pause_generator(generator)};
// Delay processing of that request by using delayed message.
so_5::send_delayed<poll_device_events_request_t>(primary_channel, pause);
}
)
);
while (!stop) {
so_5::select( prepared );
}
}
// Let's create two channels -
// Channel 1 -> process a request and post a message to channel 2
// Channel 2 -> process a request and post a message to channel 1
int main() {
std::shared_ptr<so_5::wrapped_env_t> s_node_env_obj_ = std::make_shared<so_5::wrapped_env_t>();
auto primary_channel_ = so_5::create_mchain(*s_node_env_obj_);
auto primary_channel_closer = so_5::auto_close_drop_content(primary_channel_);
auto secondary_channel_ = so_5::create_mchain(*s_node_env_obj_);
auto secondary_channel_closer = so_5::auto_close_drop_content(secondary_channel_);
// Thread objects for workers.
std::thread nthread_ {thread_func, primary_channel_, secondary_channel_};
auto nthread_joiner = so_5::auto_join( nthread_ );
// Initiate the first message.
so_5::send<poll_device_events_request_t>(primary_channel_);
nthread_.join();
return 0;
}