initial runloop implementation
[chaz/yoink] / src / moof / runloop.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "hash.hh"
13 #include "runloop.hh"
14 #include "timer.hh"
15
16
17 namespace moof {
18
19
20 enum registry_action
21 {
22 lookup,
23 set
24 };
25
26 static uint32_t call_registry(runloop*& runloop, registry_action action)
27 {
28 typedef stlplus::hash<uint32_t,moof::runloop*,hash_function> table_t;
29 static table_t table;
30
31 uint32_t thread_id = thread::current_identifier();
32
33 static MOOF_DECLARE_MUTEX(table_mutex);
34 MOOF_MUTEX_LOCK(table_mutex);
35
36 switch (action)
37 {
38 case set:
39 {
40 if (runloop) table[thread_id] = runloop;
41 else table.erase(thread_id);
42 break;
43 }
44
45 case lookup:
46 {
47 table_t::iterator it = table.find(thread_id);
48 if (it != table.end()) runloop = (*it).second;
49 break;
50 }
51 }
52
53 return thread_id;
54 }
55
56
57 int runloop::run()
58 {
59 #if ENABLE_THREADS
60 runloop* runloop = this;
61 thread_id_ = call_registry(runloop, set);
62 #endif
63
64 stop_ = false;
65 while (!stop_)
66 {
67 scalar next_event = SCALAR(0.0);
68 {
69 MOOF_MUTEX_LOCK(timers_mutex_);
70
71 for (timers_it_ = timers_.begin();
72 timers_it_ != timers_.end();
73 ++timers_it_)
74 {
75 scalar absolute = (*timers_it_)->fire_if_expired();
76 if (next_event == SCALAR(0.0) ||
77 (absolute != SCALAR(0.0) && absolute < next_event))
78 {
79 next_event = absolute;
80 }
81 }
82 }
83 timer::sleep(next_event, timer::absolute);
84 }
85
86 return code_;
87 }
88
89
90 runloop::~runloop()
91 {
92 runloop* runloop = 0;
93 call_registry(runloop, set);
94 }
95
96
97 void runloop::stop(int code)
98 {
99 code_ = code;
100 stop_ = true;
101 }
102
103
104 runloop* runloop::current()
105 {
106 runloop* runloop;
107 call_registry(runloop, lookup);
108 return runloop;
109 }
110
111
112 void runloop::add_timer(timer* timer)
113 {
114 #if ENABLE_THREADS
115 if (thread_id_ != thread::current_identifier())
116 {
117 MOOF_MUTEX_LOCK(timers_mutex_);
118 timers_.insert(timer);
119 timers_it_ = timers_.end();
120 }
121 else
122 #endif
123 {
124 timers_.insert(timer);
125 timers_it_ = timers_.end();
126 }
127 }
128
129 void runloop::remove_timer(timer* timer)
130 {
131 #if ENABLE_THREADS
132 if (thread_id_ != thread::current_identifier())
133 {
134 MOOF_MUTEX_LOCK(timers_mutex_);
135 timers_.erase(timer);
136 timers_it_ = timers_.end();
137 }
138 else
139 #endif
140 {
141 timers_.erase(timer);
142 timers_it_ = timers_.end();
143 }
144 }
145
146
147 } // namespace moof
148
This page took 0.038677 seconds and 4 git commands to generate.