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
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?
Pingback: A C++ Background Ticker, now with Rx.cpp | DLed : Music / Photography / Programming / Notes