Need help in implementation of a timer/ticker class in C++ - c++

Need help in implementing a ticker class with start/stop/pause functionality, assignable callback (onTick) with execution on a separate thread every interval span. Interval span is specifiable and update-able. Hopefully it should be cross-platform.
Here is my naive attempt, but it's not good (the while loop in start() is blocking currently, but ideally it should run on a separate thread but I can't figure out how to achieve it) as I'm pretty noob in C++ multithreading model:
#include <cstdint>
#include <functional>
#include <chrono>
#include <thread>
#include <future>
class Ticker {
public:
typedef std::chrono::duration<int64_t, std::nano> tick_interval_t;
typedef std::function<void()> on_tick_t;
Ticker (std::function<void()> onTick, std::chrono::duration<int64_t, std::nano> tickInterval)
: _onTick (onTick)
, _tickInterval (tickInterval)
, _running (false) {}
~Ticker () {}
void start () {
if (_running) return;
_running = true;
while (_running) {
std::async( std::launch::async, _onTick );
std::this_thread::sleep_for( _tickInterval );
}
}
void stop () { _running = false; }
private:
on_tick_t _onTick;
tick_interval_t _tickInterval;
bool _running;
};
I'm a completely wrong in my attempt or it's pretty close?

Consider the following code with example of usage. I hope I understood you correctly.
Just run your while loop in a separate thread.
#include <cstdint>
#include <functional>
#include <chrono>
#include <thread>
#include <future>
#include <condition_variable>
#include <iostream>
#include <mutex>
class Ticker {
public:
typedef std::chrono::duration<int64_t, std::nano> tick_interval_t;
typedef std::function<void()> on_tick_t;
Ticker (std::function<void()> onTick, std::chrono::duration<int64_t, std::nano> tickInterval)
: _onTick (onTick)
, _tickInterval (tickInterval)
, _running (false) {}
~Ticker () {}
void start () {
if (_running) return;
_running = true;
std::thread run(&Ticker::timer_loop, this);
run.detach();
}
void stop () { _running = false; }
void setDuration(std::chrono::duration<int64_t, std::nano> tickInterval)
{
_tickIntervalMutex.lock();
_tickInterval = tickInterval;
_tickIntervalMutex.unlock();
}
private:
void timer_loop()
{
while (_running) {
std::thread run(_onTick );
run.detach();
_tickIntervalMutex.lock();
std::chrono::duration<int64_t, std::nano> tickInterval = _tickInterval;
_tickIntervalMutex.unlock();
std::this_thread::sleep_for( tickInterval );
}
}
on_tick_t _onTick;
tick_interval_t _tickInterval;
volatile bool _running;
std::mutex _tickIntervalMutex;
};
void tick()
{
std::cout << "tick\n";
}
void main()
{
std::chrono::duration<int, std::milli> timer_duration1(1000);
std::chrono::duration<int, std::milli> timer_duration2(500);
std::chrono::duration<int> main_wait(5);
Ticker ticker(std::function<void()>(tick), timer_duration1);
ticker.start();
std::this_thread::sleep_for(main_wait);
ticker.setDuration(timer_duration2);
std::this_thread::sleep_for(main_wait);
ticker.stop();
}

Related

Using a boost::asio::deadline_timer per thread not working

I'm newbie here, so if I have any errors just tell me.
The problem is that I have two processes and I want them to execute concurrently because they take too much time. So I thought to implement a class timer which manage its own boost::asio::io_service and create a thread for this io_service. The code is the following:
timer.hpp
#include <iostream>
#include <string>
#include <functional>
#include <thread>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
class timer
{
public:
timer(std::function<void(void)> task,
int time)
: io__(),
timer__(io__, boost::posix_time::milliseconds(time)),
repetitive_task__(task),
time_wait__(time)
{
timer__.async_wait(boost::bind(&timer::loop, this));
}
void start()
{
thread__ = std::thread([this](){
io__.run();
});
thread__.join();
}
void loop()
{
repetitive_task__();
timer__.expires_at(timer__.expires_at() + boost::posix_time::milliseconds(time_wait__));
timer__.async_wait(boost::bind(&timer::loop, this));
}
void stop()
{
timer__.cancel();
io__.stop();
}
private:
boost::asio::io_service io__;
boost::asio::deadline_timer timer__;
std::function<void(void)> repetitive_task__;
int time_wait__;
std::thread thread__;
};
For testing it, I have the simplest main I could think:
main.cpp
#include "timer.hpp"
void test1()
{
printf("action1 \n");
}
void test2()
{
printf("action 2 \n");
}
int main(int argc, char* argv[])
{
timer timer1(&test1, 100);
timer timer2(&test2, 50);
timer1.start();
timer2.start();
return 0;
}
And the result is always action1. Never action2.
I've been looking for how to implement timers properly like in this post or in this example of boost, but I still don't understand what I am doing wrong.
Thanks in advance

event dispatcher using std::unique_ptr and std::deque in c++11

I have just written the source code below to dispatch events properly by using std::unique_ptr and std::deque, but I am not sure how accurate it is. I know it is not a good question but could someone evaluate it, is there any weird issue? In addition, I don't have any performance concern.
Thanks in advance.
- Volkan
#include <iostream>
#include <deque>
#include <mutex>
#include <memory>
#include <chrono>
#include <thread>
using namespace std;
class Event {
public:
Event(int a) : m_a(a)
{ }
void print()
{
cout << m_a << endl;
}
private:
int m_a;
};
class EventQueue {
public:
unique_ptr<Event> pop()
{
lock_guard<mutex> lock(m_Mutex);
unique_ptr<Event> p = nullptr;
if (!m_Queue.empty()) {
p = move(m_Queue.back());
m_Queue.pop_back();
}
return p;
}
void push(unique_ptr<Event> p)
{
lock_guard<mutex> lock(m_Mutex);
m_Queue.push_front(move(p));
}
private:
deque<unique_ptr<Event>> m_Queue;
mutex m_Mutex;
};
EventQueue evq;
void EventHandler()
{
while (true) {
unique_ptr<Event> p = evq.pop();
if (p)
p->print();
else
this_thread::sleep_for(chrono::seconds(10));
}
}
int main()
{
std::thread first (EventHandler);
while (true) {
int a;
cin >> a;
unique_ptr<Event> ev(new Event(a));
evq.push(move(ev));
}
first.join();
return 0;
}

Emit safely a signal from a thread and connect it to a widget

I'm using Gtkmm and multithreading.
I have a class "NetworkWorker" doig stuffs with the network in a secondary thread.
In this class i want to make many signals which will be handled by my class "MainWindow".
The methods which handle these signals, will edit append text in a TextView.
I have the following code:
NetworkWorker.h
#ifndef NETWORKWORKER_H_
# define NETWORKWORKER_H_
# include <sigc++/sigc++.h>
# include <glibmm/threads.h>
# include <string>
class NetworkWorker
{
public:
NetworkWorker();
~NetworkWorker();
void start();
void stop();
sigc::signal<void, std::string&>& signal_data_received();
private:
void run();
sigc::signal<void, std::string&> m_signal_data_received;
Glib::Threads::Thread* m_thread;
Glib::Threads::Mutex m_mutex;
bool m_stop;
};
#endif
NetworkWorker.c
#include <cstdlib>
#include <glibmm/timer.h>
#include <glibmm/threads.h>
#include <iostream>
#include <sigc++/sigc++.h>
#include "NetworkWorker.h"
NetworkWorker::NetworkWorker() :
m_thread(NULL), m_stop(false)
{
}
NetworkWorker::~NetworkWorker()
{
stop();
}
void NetworkWorker::start()
{
if (!m_thread)
m_thread = Glib::Threads::Thread::create(sigc::mem_fun(*this, &NetworkWorker::run));
}
void NetworkWorker::stop()
{
{
Glib::Threads::Mutex::Lock lock(m_mutex);
m_stop = true;
}
if (m_thread)
m_thread->join();
}
sigc::signal<void, std::string&>& NetworkWorker::signal_data_received()
{
return m_signal_data_received;
}
void NetworkWorker::run()
{
while (true)
{
{
Glib::Threads::Mutex::Lock lock(m_mutex);
if (m_stop)
break;
}
Glib::usleep(5000);
std::cout << "Thread" << std::endl;
std::string* str = new std::string("MyData");
m_signal_data_received.emit(*str);
}
}
MainWindow.h
#ifndef MAIN_WINDOW_H_
# define MAIN_WINDOW_H_
# include <gtkmm/textview.h>
# include <gtkmm/window.h>
# include <string>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
~MainWindow();
void appendText(const std::string& str);
private:
Gtk::TextView m_text_view;
};
#endif
MainWindow.c
#include <gtkmm/notebook.h>
#include <gtkmm/widget.h>
#include <iostream>
#include <string>
#include "MainWindow.h"
MainWindow::MainWindow()
{
set_title("My App");
set_default_size(800, 600);
add(m_text_view);
}
MainWindow::~MainWindow()
{
}
void MainWindow::appendText(const std::string& str)
{
std::string final_text = str + "\n";
Glib::RefPtr<Gtk::TextBuffer> buffer = m_text_view.get_buffer();
Gtk::TextBuffer::iterator it = buffer->end();
buffer->insert(it, final_text);
Glib::RefPtr<Gtk::Adjustment> adj = m_text_view.get_vadjustment();
adj->set_value(adj->get_upper() - adj->get_page_size());
}
and my main.cpp
#include <cstdlib>
#include <gtkmm/main.h>
#include <iostream>
#include <string>
#include "MainWindow.h"
#include "NetworkWorker.h"
void recv(const std::string& str)
{
std::cout << str << std::endl;
}
int main(int argc, char **argv)
{
Gtk::Main app(Gtk::Main(argc, argv));
MainWindow main_window;
NetworkWorker network_worker;
main_window.show_all();
network_worker.signal_data_received().connect(sigc::ptr_fun(&recv));
network_worker.signal_data_received().connect(sigc::mem_fun(main_window, &MainWindow::appendText));
network_worker.start();
Gtk::Main::run(main_window);
return (EXIT_SUCCESS);
}
These snippetes have been a re-adapted for this question, so maybe some change is incoherent.
When I execute this code, I have the following output:
$> ./client
Thread
MyData
Thread
MyData
[...]
Thread
MyData
Thread
MyData
(client:5596): Gtk-CRITICAL **: gtk_text_layout_real_invalidate: assertion 'layout->wrap_loop_count == 0' failed
Thread
MyData
Thread
MyData
[...]
Thread
MyData
Thread
MyData
[1] 5596 segmentation fault (core dumped) ./client
Can some one help me to resolve this issue ? :)
The issue is you are calling non threadsafe function call (signal callbacks are not threadsafe).
So you need to use something like Glib::signal_idle().connect( sigc::mem_fun(*this, &IdleExample::on_idle) );(or whatever is equivalent to C API call g_idle_add(GCallback func)) from your thread. This function is threadsafe (at least the one from the C API).
See this tutorial for a simplified example.
Never call or signal from different threads when using UI libraries. Usually the APIs are designed to be called from a single thread. This is the single most often made mistake when using UI toolkits.

Waiting for async operations

I want to implement a mechanism that allows me to block program flow until an async operation has completed. (Mostly to be used in unit tests where there is no message loop.)
The code I have creates a thread and waits for a condition notification inside the thread:
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <memory>
#include <mutex>
#include <stdexcept>
#include <thread>
struct Blocker {
Blocker() :
wait_thread([this]() {
std::mutex mtx;
std::unique_lock<std::mutex> lck(mtx);
cond.wait(lck);
})
{
}
void wait() { wait_thread.join(); }
void notify() { cond.notify_one(); }
std::condition_variable cond;
std::thread wait_thread;
};
template<typename Callback>
void async_operation(const Callback & cb) { cb(); }
int main() {
Blocker b;
async_operation([&](){ b.notify(); });
b.wait();
}
The problem is that it often deadlocks because the call to notify occurs before the thread even started. How should I fix this?
#include <mutex>
#include <condition_variable>
struct blocker
{
blocker () : done (false) {}
void
notify ()
{
std::unique_lock<std::mutex> lock (m);
done = true;
c.notify_all ();
}
void
wait ()
{
std::unique_lock<std::mutex> lock (m);
while (!done)
c.wait (lock);
}
bool done;
std::mutex m;
std::condition_variable c;
};

How to make class member function as thread function using boost

I am going to write an adapter class. In this class there is an xmlrpc-c server (abyss server). I want to start the server by creating a new thread, and the thread's function is the member function XMLThreadFun().
When I try to use the code below there is an error at the line of the adapter's constructor implementation:
/usr/include/boost/bind/bind.hpp:69:37: error: ‘void (Adapter::*)()’ is not a class, struct, or union type
Can anyone tell me how to solve this error, or how to achieve my goal? I really appreciate it.
Below is my code snippet:
#ifdef _MSC_VER
#pragma warning( disable : 4503 4355 4786 )
#else
#include "config.h"
#endif
#include "quickfix/FileStore.h"
#include "quickfix/SocketInitiator.h"
#include "quickfix/SessionSettings.h"
#include "Application.h"
#include <string>
#include <iostream>
#include <fstream>
#include "quickfix/SessionID.h"
#include "quickfix/Session.h"
#include "getopt-repl.h"
#include <cassert>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.hpp>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
using namespace std;
class theClient : public xmlrpc_c::method {
public:
theClient() {}
theClient(FIX::SocketInitiator* initiator) {
set<FIX::SessionID> s(initiator->getSessions());
set<FIX::SessionID>::iterator myIterator;
for (myIterator = s.begin(); myIterator != s.end(); myIterator++) {
string str(myIterator->getSenderCompID());
clientname = str;
}
}
void execute(xmlrpc_c::paramList const& paramList,
xmlrpc_c::value * const retvalP) {
*retvalP = xmlrpc_c::value_string(clientname);
}
private:
string clientname;
};
class Adapter {
private:
xmlrpc_c::registry myRegistry;
xmlrpc_c::methodPtr XMLRPCMethodP;
xmlrpc_c::serverAbyss webServer;
boost::thread webServerThread;
public:
void initWebServer(string rpcHost, string rpcPort);
void XMLThreadFun();
Adapter(string rpcHost, string rpcPort);
};
Adapter::Adapter(string rpcHost, string rpcPort) : myRegistry(), XMLRPCMethodP(new theClient), webServer(myRegistry, 8181, "/tmp/xmlrpc_log"), webServerThread(boost::bind(&Adapter::XMLThreadFun, this, &webServer))
{
initWebServer(rpcHost, rpcPort);
}
void Adapter::XMLThreadFun() {
webServer->run();
}
void Adapter::initWebServer(string rpcHost, string rpcPort) {
webServerThread.join();
}
You will need to use boost::bind to call a member function as a thread.
Something like
class MyClass {
public:
void Start();
void DoStuff( int limit );
};
MyClass foo;
boost::thread thread1( boost::bind( &MyClass::Start, &foo ) );
boost::thread thread2( boost::bind( &MyClass::DoStuff, &foo, 30 ) );
// threads do stuff here
thread1.join();
thread2.join();
Specifically here, it looks like you would change
webServerThread( boost::bind( &Adapter::XMLThreadFun, this, &webServer)
to
webServerThread( boost::bind( &Adapter::XMLThreadFun, this )
No need to use boost::bind
boost::thread thread2( boost::bind( &MyClass::DoStuff, &foo, 30 ) );
is equivalent to:
boost::thread thread2( &MyClass::DoStuff, &foo, 30 );