In this question, I asked for feedback on a class that provided my program with periodical signals. I have rewritten that class based on the feedback from the accepted answer. As this again uses a complex library I've never worked with before, I'd really appreciate some feedback!
The class runs a function in a separate thread using std::async
. Every interval
seconds, this function sends a 'tick' to the other parts of my program using my ZeroMQ wrapper classes Client
and Message
. This is thread-safe, because all other behaviour in my program is also triggered via messages read by the same ZeroMQ socket that is reading these 'ticks'.
Some notes:
- In the accepted answer to the previous question, it was suggested to use chrono literals, but as I am restricted to gcc 4.8.5 and thus c++11, I can't do this, so I am using an
int
respresenting a number of seconds. - I instantiate
Client
in the asynchronously called function so it cannot be used from another thread, but I should probably move the instantiation to the constructor as it uses a ZeroMQ context that is created in another thread. - The accepted answer to the previous question included some generalizations. I left these out of my implementation, because they were unnecessary in this application and this kept the code simpler.
async_future
is not used, but I need to store it, otherwiseasync
won't return.
And finally, the actual code:
Ticker.hpp
#ifndef TICKER_HPP
#define TICKER_HPP
#include <future>
#include "ipc/Client.hpp"
#include "ipc/Message.hpp"
namespace sdp {
class Ticker {
private:
const std::chrono::seconds interval;
std::promise<void> done_promise;
std::shared_future<void> done_future;
std::future<void> async_future;
public:
Ticker(unsigned int interval);
Ticker(const Ticker& orig) = delete;
virtual ~Ticker();
void stop();
private:
void tickfunction();
};
}
#endif /* TICKER_HPP */
Ticker.cpp
#include "Ticker.hpp"
#include <chrono>
using namespace std;
using namespace sdp;
Ticker::Ticker(unsigned int interval)
: interval(interval), done_promise(), done_future(done_promise.get_future()) {
async_future = async(launch::async, &Ticker::tickfunction, this);
}
Ticker::~Ticker() {
stop();
}
void Ticker::stop() {
done_promise.set_value();
}
void Ticker::tickfunction() {
Client socket("inproc://ticker");
std::future_status status;
do {
status = done_future.wait_for(interval);
if (status == std::future_status::timeout) {
Message message;
message.addEmptyPart();
message.add("tick");
socket.send(message);
}
} while (status != std::future_status::ready);
}