]> Dogcows Code - chaz/yoink/blobdiff - src/moof/runloop.cc
initial runloop implementation
[chaz/yoink] / src / moof / runloop.cc
diff --git a/src/moof/runloop.cc b/src/moof/runloop.cc
new file mode 100644 (file)
index 0000000..db59814
--- /dev/null
@@ -0,0 +1,148 @@
+
+/*]  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
+
This page took 0.019102 seconds and 4 git commands to generate.