Simplest threaded example
Horacio Sanson
hsanson at gmail.com
Thu Jul 29 04:28:46 CEST 2010
After reading several times the documentation/mailing list this is the simplest
threading model I found to work with libev (C++):
#define EV_STANDALONE 1
#define EV_FEATURES 8
#define EV_USE_EPOLL 1
#define EV_PREPARE_ENABLE 1
#define EV_IDLE_ENABLE 1
#define EV_SIGNAL_ENABLE 1
#define EV_CHILD_ENABLE 1
#define EV_USE_STDEXCEPT 0
//#define EV_CONFIG_H <config.h>
#include <ev++.h>
#include "ev.c"
#include <boost/thread.hpp>
#include <iostream>
#include <string>
#include <sstream>
class Server
{
private:
struct ev_loop *m_loop;
mutable boost::mutex m_mutex;
mutable boost::mutex m_coutMutex;
ev::io m_stdinWatcher;
ev::sig m_sigintWatcher;
ev::sig m_sigtermWatcher;
void print() {
boost::mutex::scoped_lock lock(m_coutMutex);
std::string input = "";
std::getline(std::cin, input);
std::cout << "Thread: " << boost::this_thread::get_id() << " echo: " << input << std::endl;
}
void sigint_cb(ev::sig &w, int revents) {
ev_unloop(m_loop, EVUNLOOP_ALL);
}
void stdin_cb(ev::io &w, int revents) {
m_mutex.unlock();
print();
m_mutex.lock();
}
void worker_thread() {
m_mutex.lock();
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
ev_loop(m_loop, 0);
m_mutex.unlock();
}
public:
Server() {
m_loop = ev_default_loop(0);
m_stdinWatcher.set<Server, &Server::stdin_cb>(this);
m_sigintWatcher.set <Server, &Server::sigint_cb>(this);
m_sigtermWatcher.set <Server, &Server::sigint_cb>(this);
}
~Server() {
m_stdinWatcher.stop();
m_sigintWatcher.stop();
m_sigtermWatcher.stop();
ev_default_destroy();
}
void lock() {
m_mutex.lock();
}
void unlock() {
m_mutex.unlock();
}
void start() {
m_stdinWatcher.start(0, ev::READ);
m_sigintWatcher.start(SIGINT);
m_sigtermWatcher.start(SIGTERM);
// Worker threads handle event callbacks and add/remove watchers
boost::thread_group threads;
for (int i = 0; i < 2; ++i)
threads.create_thread(boost::bind(&Server::worker_thread, this));
threads.join_all();
}
};
int main(int argc, char **argv)
{
Server server;
server.start();
}
This is for a small online board game were most of the requests are short (piece
move/update game state) but some requests need DB access that can take several
milliseconds (~500ms) and some other requests can block for some time waiting
for other players updates/timeouts.
The question would be: is this an acceptable threading model for libev and my
application?
Is this a correct way of doing threading with libev?? because helgrind complains
a lot about possible race conditions with this code but I think is due to boost
and not libev.
Any improvements/comments/fixes are welcome....
--
regards,
Horacio Sanson
More information about the libev
mailing list