Unfortunately, the Reactive Extensions for C++ (Rx++) did not work for me as smoothly as their C# counterpart. My goal is to recreate the background ticker from the Rx version. The first, and perhaps not the last example implementation will be using the Parallel Patterns Library by Microsoft, which uses the Concurrency Runtime. The goal is to write a code that abstracts the threads away, and uses some background scheduler to schedule calls to functions in an asynchronous manner.
Here, asynchronous calls will be done by tickers, one of which will poll a value from a bogus frequency meter and write it to the console, whereas the other one will just write “tick”.
First, the frequency meter that gives random values around 62 (a magic number):
#include <mutex>
#include <random>
class FrequencyMeter
{
mutable std::mt19937 gen;
std::uniform_int_distribution<int> dis;
mutable std::mutex m;
public:
FrequencyMeter() :
dis(0,3),
gen(std::random_device()())
{}
int Hz() const
{
std::lock_guard<std::mutex> lock(m);
return 60+dis(gen);
}
};
This class is not the primary concern here, but if the Hz value is accessed from multiple threads, the access should perhaps be serialized (by a mutex here).
Now, one of the side wishes for the ticker is the ability to start and stop it any time. The ticker should also not care what it executes, hence we can take an std::function for now, or perhaps anything callable. Howerver, having c++11 lambdas, it’s easy to convert to standard function (thread-safety and ownership issues notwithstanding yet). Following the examples for cancellation tokens, one can write a small wrapper that will tick at predefined intervals (see full code), wrapping a simple loop:
while (running)
{
// Check for cancellation.
if (concurrency::is_task_cancellation_requested())
{
running = false;
concurrency::cancel_current_task();
}
else
{
this->tick_once();
concurrency::wait(interval);
}
}
In the small test program, the frequency meter is instantiated and the first ticker is started, ticking once a quarter of a second:
FrequencyMeter FM;
active_ticker measure([&FM]{std::cout<<FM.Hz()<<std::endl;});
measure.start(250);
Then another ticker is started:
active_ticker ticker([]{std::cout<<"tick"<<std::endl;});
ticker.start(500);
And some wait, start and stop logic:
wait(2000); //see the output for a couple of seconds
measure.stop(); //stop the frequency meter
wait(2000); //wait some more
ticker.stop(); //stop ticking
measure.start(250); //start measuring again
wait(2000); //and wait a bit more
measure.stop();
The output looks like this:
60
tick
61
62
tick
61
62
tick
60
60
Canceling measurement ...
tick
60
tick
tick
tick
Restarting measurement ...
tick
60
63
62
61
62
62
62
Done
Any other technology to try elegant ticking (tinkering) with? TBB, zeromq in process?