/*] Copyright (c) 2009-2010, Charles McGarvey [************************** **] All rights reserved. * * vi:ts=4 sw=4 tw=75 * * Distributable under the terms and conditions of the 2-clause BSD license; * see the file COPYING for a complete text of the license. * **************************************************************************/ #include "hash.hh" #include "runloop.hh" #include "timer.hh" namespace moof { enum registry_action { lookup, set }; static uint32_t call_registry(runloop*& runloop, registry_action action) { typedef stlplus::hash table_t; static table_t table; uint32_t thread_id = thread::current_identifier(); static MOOF_DECLARE_MUTEX(table_mutex); MOOF_MUTEX_LOCK(table_mutex); switch (action) { case set: { if (runloop) table[thread_id] = runloop; else table.erase(thread_id); break; } case lookup: { table_t::iterator it = table.find(thread_id); if (it != table.end()) runloop = (*it).second; break; } } return thread_id; } int runloop::run() { #if ENABLE_THREADS runloop* runloop = this; thread_id_ = call_registry(runloop, set); #endif stop_ = false; while (!stop_) { scalar next_event = SCALAR(0.0); { MOOF_MUTEX_LOCK(timers_mutex_); for (timers_it_ = timers_.begin(); timers_it_ != timers_.end(); ++timers_it_) { scalar absolute = (*timers_it_)->fire_if_expired(); if (next_event == SCALAR(0.0) || (absolute != SCALAR(0.0) && absolute < next_event)) { next_event = absolute; } } } timer::sleep(next_event, timer::absolute); } return code_; } runloop::~runloop() { runloop* runloop = 0; call_registry(runloop, set); } void runloop::stop(int code) { code_ = code; stop_ = true; } runloop* runloop::current() { runloop* runloop; call_registry(runloop, lookup); return runloop; } void runloop::add_timer(timer* timer) { #if ENABLE_THREADS if (thread_id_ != thread::current_identifier()) { MOOF_MUTEX_LOCK(timers_mutex_); timers_.insert(timer); timers_it_ = timers_.end(); } else #endif { timers_.insert(timer); timers_it_ = timers_.end(); } } void runloop::remove_timer(timer* timer) { #if ENABLE_THREADS if (thread_id_ != thread::current_identifier()) { MOOF_MUTEX_LOCK(timers_mutex_); timers_.erase(timer); timers_it_ = timers_.end(); } else #endif { timers_.erase(timer); timers_it_ = timers_.end(); } } } // namespace moof