#include #include #include #include "stg/locker.h" #include "stg/common.h" #include "eventloop.h" EVENT_LOOP::EVENT_LOOP() : ACTIONS_LIST(), _running(false), _stopped(true), _tid(), _mutex(), _condition() { pthread_mutex_init(&_mutex, NULL); pthread_cond_init(&_condition, NULL); } EVENT_LOOP::~EVENT_LOOP() { pthread_cond_destroy(&_condition); pthread_mutex_destroy(&_mutex); } bool EVENT_LOOP::Start() { _running = true; if (pthread_create(&_tid, NULL, Run, this)) { printfd(__FILE__, "EVENT_LOOP::Start - Failed to create thread: '%s'\n", strerror(errno)); return true; } return false; } bool EVENT_LOOP::Stop() { _running = false; // Wake up thread pthread_cond_signal(&_condition); // Wait until thread exit pthread_join(_tid, NULL); return false; } void * EVENT_LOOP::Run(void * self) { EVENT_LOOP * ev = static_cast(self); ev->Runner(); return NULL; } void EVENT_LOOP::Runner() { sigset_t signalSet; sigfillset(&signalSet); pthread_sigmask(SIG_BLOCK, &signalSet, NULL); _stopped = false; printfd(__FILE__, "EVENT_LOOP::Runner - Before start\n"); while (_running) { { STG_LOCKER lock(&_mutex); // Check for any actions... if (empty()) { // ... and sleep until new actions added printfd(__FILE__, "EVENT_LOOP::Runner - Sleeping until new actions arrived\n"); pthread_cond_wait(&_condition, &_mutex); } // Check for running after wake up if (!_running) { // Don't process any actions if stopping break; } } // Create new empty actions list ACTIONS_LIST local; // Fast swap with current swap(local); // Invoke all current actions printfd(__FILE__, "EVENT_LOOP::Runner - Invoke %d actions\n", local.size()); local.InvokeAll(); } printfd(__FILE__, "EVENT_LOOP::Runner - Before stop\n"); _stopped = true; } namespace { pthread_mutex_t singletonMutex; } EVENT_LOOP & EVENT_LOOP_SINGLETON::GetInstance() { // Double-checking technique if (!_instance) { STG_LOCKER lock(&singletonMutex); if (!_instance) { CreateInstance(); } } return *_instance; } void EVENT_LOOP_SINGLETON::CreateInstance() { static EVENT_LOOP loop; _instance = &loop; } EVENT_LOOP * EVENT_LOOP_SINGLETON::_instance = NULL;