|
Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
|
00001 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __RAPICORN_LOOP_HH__ 00003 #define __RAPICORN_LOOP_HH__ 00004 00005 #include <rcore/utilities.hh> 00006 #include <rcore/rapicornthread.hh> 00007 #include <rcore/rapicornsignal.hh> 00008 00009 00010 namespace Rapicorn { 00011 00012 // === PollFD === 00013 struct PollFD 00014 { 00015 int fd; 00016 uint16 events; 00017 uint16 revents; 00019 enum { 00020 IN = RAPICORN_SYSVAL_POLLIN, 00021 PRI = RAPICORN_SYSVAL_POLLPRI, 00022 OUT = RAPICORN_SYSVAL_POLLOUT, 00023 RDNORM = RAPICORN_SYSVAL_POLLRDNORM, 00024 RDBAND = RAPICORN_SYSVAL_POLLRDBAND, 00025 WRNORM = RAPICORN_SYSVAL_POLLWRNORM, 00026 WRBAND = RAPICORN_SYSVAL_POLLWRBAND, 00027 /* Event types updated in .revents regardlessly */ 00028 ERR = RAPICORN_SYSVAL_POLLERR, 00029 HUP = RAPICORN_SYSVAL_POLLHUP, 00030 NVAL = RAPICORN_SYSVAL_POLLNVAL, 00031 }; 00032 }; 00033 00034 // === EventFd === 00035 class EventFd 00036 { 00037 int fds[2]; 00038 public: 00039 explicit EventFd (); 00040 int open (); 00041 bool opened (); 00042 void wakeup (); 00043 int inputfd (); 00044 bool pollin (); 00045 void flush (); 00046 /*Des*/ ~EventFd (); 00047 }; 00048 00049 // === EventLoop === 00050 class MainLoop; 00051 class EventLoop : public virtual BaseObject 00052 { 00053 class TimedSource; 00054 class PollFDSource; 00055 friend class MainLoop; 00056 public: 00057 class Source; 00058 class State; 00059 protected: 00060 typedef std::vector<Source*> SourceList; 00061 MainLoop &m_main_loop; 00062 SourceList m_sources; 00063 int64 m_dispatch_priority; 00064 SourceList m_poll_sources; 00065 explicit EventLoop (MainLoop&); 00066 virtual ~EventLoop (); 00067 Source* find_first_L (); 00068 Source* find_source_L (uint id); 00069 bool has_primary_L (void); 00070 void remove_source_Lm (Source *source); 00071 void kill_sources_Lm (void); 00072 void unpoll_sources_U (); 00073 void collect_sources_Lm (State&); 00074 bool prepare_sources_Lm (State&, int64*, vector<PollFD>&); 00075 bool check_sources_Lm (State&, const vector<PollFD>&); 00076 Source* dispatch_source_Lm (State&); 00077 typedef Signals::Slot1<void,PollFD&> VPfdSlot; 00078 typedef Signals::Slot1<bool,PollFD&> BPfdSlot; 00079 public: 00080 static const int PRIORITY_NOW = -1073741824; 00081 static const int PRIORITY_HIGH = -100 - 10; 00082 static const int PRIORITY_NEXT = -100 - 5; 00083 static const int PRIORITY_NOTIFY = 0 - 1; 00084 static const int PRIORITY_NORMAL = 0; 00085 static const int PRIORITY_UPDATE = +100 + 5; 00086 static const int PRIORITY_IDLE = +200; 00087 static const int PRIORITY_BACKGROUND = +300 + 500; 00088 void wakeup (); 00089 // source handling 00090 uint add (Source *loop_source, 00091 int priority = PRIORITY_IDLE); 00092 void remove (uint id); 00093 bool try_remove (uint id); 00094 void kill_sources (void); 00095 bool has_primary (void); 00096 uint exec_now (const VoidSlot &sl); 00097 uint exec_now (const BoolSlot &sl); 00098 uint exec_next (const VoidSlot &sl); 00099 uint exec_next (const BoolSlot &sl); 00100 uint exec_notify (const VoidSlot &sl); 00101 uint exec_notify (const BoolSlot &sl); 00102 uint exec_normal (const VoidSlot &sl); 00103 uint exec_normal (const BoolSlot &sl); 00104 uint exec_update (const VoidSlot &sl); 00105 uint exec_update (const BoolSlot &sl); 00106 uint exec_background (const VoidSlot &sl); 00107 uint exec_background (const BoolSlot &sl); 00108 uint exec_timer (uint timeout_ms, 00109 const VoidSlot &sl, 00110 int priority = PRIORITY_NEXT); 00111 uint exec_timer (uint initial_timeout_ms, 00112 uint repeat_timeout_ms, 00113 const BoolSlot &sl, 00114 int priority = PRIORITY_NEXT); 00115 uint exec_io_handler (const VPfdSlot &sl, 00116 int fd, 00117 const String &mode, 00118 int priority = PRIORITY_NORMAL); 00119 uint exec_io_handler (const BPfdSlot &sl, 00120 int fd, 00121 const String &mode, 00122 int priority = PRIORITY_NORMAL); 00123 MainLoop* main_loop () const { return &m_main_loop; } 00124 }; 00125 00126 // === MainLoop === 00127 class MainLoop : public EventLoop 00128 { 00129 friend class EventLoop; 00130 friend class SlaveLoop; 00131 Mutex m_mutex; 00132 vector<EventLoop*> m_loops; 00133 EventFd m_eventfd; 00134 uint m_rr_index; 00135 bool m_running; 00136 int m_quit_code; 00137 bool finishable_L (); 00138 void wakeup_poll (); 00139 void add_loop_L (EventLoop &loop); 00140 void remove_loop_L (EventLoop &loop); 00141 bool iterate_loops_Lm (State&, bool b, bool d); 00142 explicit MainLoop (); 00143 public: 00144 virtual ~MainLoop (); 00145 int run (); 00146 void quit (int quit_code = 0); 00147 bool finishable (); 00148 bool iterate (bool block); 00149 void iterate_pending (); 00150 void kill_loops (); 00151 EventLoop* new_slave (); 00152 static MainLoop* _new (); 00153 inline Mutex& mutex () { return m_mutex; } 00154 00155 struct LockHooks { bool (*sense) (); void (*lock) (); void (*unlock) (); }; 00156 void set_lock_hooks (const LockHooks &hooks); 00157 private: LockHooks m_lock_hooks; 00159 }; 00160 00161 // === EventLoop::State === 00162 struct EventLoop::State { 00163 uint64 current_time_usecs; 00164 bool seen_primary; 00165 State(); 00166 }; 00167 00168 // === EventLoop::Source === 00169 class EventLoop::Source : public virtual ReferenceCountable, protected NonCopyable 00170 { 00171 friend class EventLoop; 00172 protected: 00173 EventLoop *m_loop; 00174 struct { 00175 PollFD *pfd; 00176 uint idx; 00177 } *m_pfds; 00178 uint m_id; 00179 int m_priority; 00180 uint16 m_loop_state; 00181 uint m_may_recurse : 1; 00182 uint m_dispatching : 1; 00183 uint m_was_dispatching : 1; 00184 uint m_primary : 1; 00185 uint n_pfds (); 00186 explicit Source (); 00187 uint source_id () { return m_loop ? m_id : 0; } 00188 public: 00189 virtual ~Source (); 00190 virtual bool prepare (const State &state, 00191 int64 *timeout_usecs_p) = 0; 00192 virtual bool check (const State &state) = 0; 00193 virtual bool dispatch (const State &state) = 0; 00194 virtual void destroy (); 00195 bool recursion () const; 00196 bool may_recurse () const; 00197 void may_recurse (bool may_recurse); 00198 bool primary () const; 00199 void primary (bool is_primary); 00200 void add_poll (PollFD * const pfd); 00201 void remove_poll (PollFD * const pfd); 00202 void loop_remove (); 00203 MainLoop* main_loop () const { return m_loop ? m_loop->main_loop() : NULL; } 00204 }; 00205 00206 // === EventLoop::TimedSource === 00207 class EventLoop::TimedSource : public virtual EventLoop::Source 00208 { 00209 uint64 m_expiration_usecs; 00210 uint m_interval_msecs; 00211 bool m_first_interval; 00212 const bool m_oneshot; 00213 union { 00214 Signals::Trampoline0<bool> *m_btrampoline; 00215 Signals::Trampoline0<void> *m_vtrampoline; 00216 }; 00217 protected: 00218 virtual ~TimedSource (); 00219 virtual bool prepare (const State &state, 00220 int64 *timeout_usecs_p); 00221 virtual bool check (const State &state); 00222 virtual bool dispatch (const State &state); 00223 public: 00224 explicit TimedSource (Signals::Trampoline0<bool> &bt, 00225 uint initial_interval_msecs = 0, 00226 uint repeat_interval_msecs = 0); 00227 explicit TimedSource (Signals::Trampoline0<void> &vt, 00228 uint initial_interval_msecs = 0, 00229 uint repeat_interval_msecs = 0); 00230 }; 00231 00232 // === EventLoop::PollFDSource === 00233 class EventLoop::PollFDSource : public virtual EventLoop::Source 00234 { 00235 protected: 00236 void construct (const String &mode); 00237 virtual ~PollFDSource (); 00238 virtual bool prepare (const State &state, 00239 int64 *timeout_usecs_p); 00240 virtual bool check (const State &state); 00241 virtual bool dispatch (const State &state); 00242 virtual void destroy (); 00243 PollFD m_pfd; 00244 uint m_ignore_errors : 1; // 'E' 00245 uint m_ignore_hangup : 1; // 'H' 00246 uint m_never_close : 1; // 'C' 00247 private: 00248 const uint m_oneshot : 1; 00249 union { 00250 Signals::Trampoline1<bool,PollFD&> *m_btrampoline; 00251 Signals::Trampoline1<void,PollFD&> *m_vtrampoline; 00252 }; 00253 public: 00254 explicit PollFDSource (Signals::Trampoline1<bool,PollFD&> &bt, 00255 int fd, 00256 const String &mode); 00257 explicit PollFDSource (Signals::Trampoline1<void,PollFD&> &vt, 00258 int fd, 00259 const String &mode); 00260 }; 00261 00262 // === EventLoop methods === 00263 inline uint 00264 EventLoop::exec_now (const VoidSlot &sl) 00265 { 00266 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NOW); 00267 } 00268 00269 inline uint 00270 EventLoop::exec_now (const BoolSlot &sl) 00271 { 00272 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NOW); 00273 } 00274 00275 inline uint 00276 EventLoop::exec_next (const VoidSlot &sl) 00277 { 00278 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NEXT); 00279 } 00280 00281 inline uint 00282 EventLoop::exec_next (const BoolSlot &sl) 00283 { 00284 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NEXT); 00285 } 00286 00287 inline uint 00288 EventLoop::exec_notify (const VoidSlot &sl) 00289 { 00290 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NOTIFY); 00291 } 00292 00293 inline uint 00294 EventLoop::exec_notify (const BoolSlot &sl) 00295 { 00296 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NOTIFY); 00297 } 00298 00299 inline uint 00300 EventLoop::exec_normal (const VoidSlot &sl) 00301 { 00302 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NORMAL); 00303 } 00304 00305 inline uint 00306 EventLoop::exec_normal (const BoolSlot &sl) 00307 { 00308 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_NORMAL); 00309 } 00310 00311 inline uint 00312 EventLoop::exec_update (const VoidSlot &sl) 00313 { 00314 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_UPDATE); 00315 } 00316 00317 inline uint 00318 EventLoop::exec_update (const BoolSlot &sl) 00319 { 00320 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_UPDATE); 00321 } 00322 00323 inline uint 00324 EventLoop::exec_background (const VoidSlot &sl) 00325 { 00326 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_BACKGROUND); 00327 } 00328 00329 inline uint 00330 EventLoop::exec_background (const BoolSlot &sl) 00331 { 00332 return add (new TimedSource (*sl.get_trampoline()), PRIORITY_BACKGROUND); 00333 } 00334 00335 inline uint 00336 EventLoop::exec_timer (uint timeout_ms, 00337 const VoidSlot &sl, 00338 int priority) 00339 { 00340 return add (new TimedSource (*sl.get_trampoline(), timeout_ms, timeout_ms), priority); 00341 } 00342 00343 inline uint 00344 EventLoop::exec_timer (uint initial_timeout_ms, 00345 uint repeat_timeout_ms, 00346 const BoolSlot &sl, 00347 int priority) 00348 { 00349 return add (new TimedSource (*sl.get_trampoline(), initial_timeout_ms, repeat_timeout_ms), priority); 00350 } 00351 00352 inline uint 00353 EventLoop::exec_io_handler (const VPfdSlot &sl, 00354 int fd, 00355 const String &mode, 00356 int priority) 00357 { 00358 return add (new PollFDSource (*sl.get_trampoline(), fd, mode), priority); 00359 } 00360 00361 inline uint 00362 EventLoop::exec_io_handler (const BPfdSlot &sl, 00363 int fd, 00364 const String &mode, 00365 int priority) 00366 { 00367 return add (new PollFDSource (*sl.get_trampoline(), fd, mode), priority); 00368 } 00369 00370 } // Rapicorn 00371 00372 #endif /* __RAPICORN_LOOP_HH__ */
1.7.4