--- /dev/null
+
+/*] 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<uint32_t,moof::runloop*,hash_function> 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
+