Rapicorn - Experimental UI Toolkit - Source Code
13.07.0
|
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/objects.hh> 00006 #include <rcore/thread.hh> 00007 00008 00009 namespace Rapicorn { 00010 00011 using Aida::EventFd; 00012 00013 // === PollFD === 00014 struct PollFD 00015 { 00016 int fd; 00017 uint16 events; 00018 uint16 revents; 00020 enum { 00021 IN = RAPICORN_SYSVAL_POLLIN, 00022 PRI = RAPICORN_SYSVAL_POLLPRI, 00023 OUT = RAPICORN_SYSVAL_POLLOUT, 00024 RDNORM = RAPICORN_SYSVAL_POLLRDNORM, 00025 RDBAND = RAPICORN_SYSVAL_POLLRDBAND, 00026 WRNORM = RAPICORN_SYSVAL_POLLWRNORM, 00027 WRBAND = RAPICORN_SYSVAL_POLLWRBAND, 00028 /* Event types updated in .revents regardlessly */ 00029 ERR = RAPICORN_SYSVAL_POLLERR, 00030 HUP = RAPICORN_SYSVAL_POLLHUP, 00031 NVAL = RAPICORN_SYSVAL_POLLNVAL, 00032 }; 00033 }; 00034 00035 // === EventLoop === 00036 class MainLoop; 00037 class EventLoop : public virtual ReferenceCountable 00038 { 00039 class TimedSource; 00040 class PollFDSource; 00041 class DispatcherSource; 00042 class QuickPfdArray; // pseudo vector<PollFD> 00043 class QuickSourceArray; // pseudo vector<Source*> 00044 friend class MainLoop; 00045 public: 00046 class Source; 00047 class State; 00048 protected: 00049 typedef std::vector<Source*> SourceList; 00050 MainLoop &main_loop_; 00051 SourceList sources_; 00052 int64 dispatch_priority_; 00053 QuickSourceArray &poll_sources_; 00054 uint64 pollmem1[3]; 00055 Source* pollmem2[7]; 00056 bool primary_; 00057 explicit EventLoop (MainLoop&); 00058 virtual ~EventLoop (); 00059 Source* find_first_L (); 00060 Source* find_source_L (uint id); 00061 bool has_primary_L (void); 00062 void remove_source_Lm (Source *source); 00063 void kill_sources_Lm (void); 00064 void unpoll_sources_U (); 00065 void collect_sources_Lm (State&); 00066 bool prepare_sources_Lm (State&, int64*, QuickPfdArray&); 00067 bool check_sources_Lm (State&, const QuickPfdArray&); 00068 Source* dispatch_source_Lm (State&); 00069 public: 00070 typedef std::function<void (void)> VoidSlot; 00071 typedef std::function<bool (void)> BoolSlot; 00072 typedef std::function<void (PollFD&)> VPfdSlot; 00073 typedef std::function<bool (PollFD&)> BPfdSlot; 00074 typedef std::function<bool (const State&)> DispatcherSlot; 00075 static const int PRIORITY_NOW = -1073741824; 00076 static const int PRIORITY_HIGH = -100 - 10; 00077 static const int PRIORITY_NEXT = -100 - 5; 00078 static const int PRIORITY_NOTIFY = 0 - 1; 00079 static const int PRIORITY_NORMAL = 0; 00080 static const int PRIORITY_UPDATE = +100 + 5; 00081 static const int PRIORITY_IDLE = +200; 00082 static const int PRIORITY_BACKGROUND = +300 + 500; 00083 void wakeup (); 00084 // source handling 00085 uint add (Source *loop_source, int priority 00086 = PRIORITY_NORMAL); 00087 void remove (uint id); 00088 bool try_remove (uint id); 00089 void kill_sources (void); 00090 bool has_primary (void); 00091 bool flag_primary (bool on); 00092 template<class BoolVoidFunctor> 00093 uint exec_now (BoolVoidFunctor &&bvf); 00094 template<class BoolVoidFunctor> 00095 uint exec_next (BoolVoidFunctor &&bvf); 00096 template<class BoolVoidFunctor> 00097 uint exec_notify (BoolVoidFunctor &&bvf); 00098 template<class BoolVoidFunctor> 00099 uint exec_normal (BoolVoidFunctor &&bvf); 00100 template<class BoolVoidFunctor> 00101 uint exec_update (BoolVoidFunctor &&bvf); 00102 template<class BoolVoidFunctor> 00103 uint exec_background (BoolVoidFunctor &&bvf); 00104 MainLoop* main_loop () const { return &main_loop_; } 00105 00106 uint exec_dispatcher (const DispatcherSlot &sl, int priority = PRIORITY_NORMAL); 00108 template<class BoolVoidFunctor> 00109 uint exec_timer (uint timeout_ms, BoolVoidFunctor &&bvf, int priority = PRIORITY_NORMAL); 00111 template<class BoolVoidFunctor> 00112 uint exec_timer (uint initial_timeout_ms, uint repeat_timeout_ms, BoolVoidFunctor &&bvf, int priority = PRIORITY_NORMAL); 00114 template<class BoolVoidPollFunctor> 00115 uint exec_io_handler (BoolVoidPollFunctor &&bvf, int fd, const String &mode, int priority = PRIORITY_NORMAL); 00116 }; 00117 00118 // === MainLoop === 00119 class MainLoop : public EventLoop 00120 { 00121 friend class EventLoop; 00122 friend class SlaveLoop; 00123 Mutex mutex_; 00124 vector<EventLoop*> loops_; 00125 EventFd eventfd_; 00126 uint rr_index_; 00127 bool running_; 00128 int quit_code_; 00129 bool finishable_L (); 00130 void wakeup_poll (); 00131 void add_loop_L (EventLoop &loop); 00132 void remove_loop_L (EventLoop &loop); 00133 bool iterate_loops_Lm (State&, bool b, bool d); 00134 explicit MainLoop (); 00135 public: 00136 virtual ~MainLoop (); 00137 int run (); 00138 bool running (); 00139 void quit (int quit_code = 0); 00140 bool finishable (); 00141 bool iterate (bool block); 00142 void iterate_pending (); 00143 void kill_loops (); 00144 EventLoop* new_slave (); 00145 static MainLoop* _new (); 00146 inline Mutex& mutex () { return mutex_; } 00147 00148 void set_lock_hooks (std::function<bool()> sense, std::function<void()> lock, std::function<void()> unlock); 00149 private: 00150 struct LockHooks { std::function<bool()> sense; std::function<void()> lock; std::function<void()> unlock; }; 00151 LockHooks lock_hooks_; bool lock_hooks_locked_; 00153 }; 00154 00155 // === EventLoop::State === 00156 struct EventLoop::State { 00157 enum Phase { NONE, COLLECT, PREPARE, CHECK, DISPATCH, DESTROY }; 00158 uint64 current_time_usecs; 00159 Phase phase; 00160 bool seen_primary; 00161 State(); 00162 }; 00163 00164 // === EventLoop::Source === 00165 class EventLoop::Source : public virtual ReferenceCountable 00166 { 00167 friend class EventLoop; 00168 RAPICORN_CLASS_NON_COPYABLE (Source); 00169 protected: 00170 EventLoop *loop_; 00171 struct { 00172 PollFD *pfd; 00173 uint idx; 00174 } *pfds_; 00175 uint id_; 00176 int priority_; 00177 uint16 loop_state_; 00178 uint may_recurse_ : 1; 00179 uint dispatching_ : 1; 00180 uint was_dispatching_ : 1; 00181 uint primary_ : 1; 00182 uint n_pfds (); 00183 explicit Source (); 00184 uint source_id () { return loop_ ? id_ : 0; } 00185 public: 00186 virtual ~Source (); 00187 virtual bool prepare (const State &state, 00188 int64 *timeout_usecs_p) = 0; 00189 virtual bool check (const State &state) = 0; 00190 virtual bool dispatch (const State &state) = 0; 00191 virtual void destroy (); 00192 bool recursion () const; 00193 bool may_recurse () const; 00194 void may_recurse (bool may_recurse); 00195 bool primary () const; 00196 void primary (bool is_primary); 00197 void add_poll (PollFD * const pfd); 00198 void remove_poll (PollFD * const pfd); 00199 void loop_remove (); 00200 MainLoop* main_loop () const { return loop_ ? loop_->main_loop() : NULL; } 00201 }; 00202 00203 // === EventLoop::DispatcherSource === 00204 class EventLoop::DispatcherSource : public virtual EventLoop::Source 00205 { 00206 DispatcherSlot slot_; 00207 protected: 00208 virtual ~DispatcherSource (); 00209 virtual bool prepare (const State &state, int64 *timeout_usecs_p); 00210 virtual bool check (const State &state); 00211 virtual bool dispatch (const State &state); 00212 virtual void destroy (); 00213 public: 00214 explicit DispatcherSource (const DispatcherSlot &slot); 00215 }; 00216 00217 // === EventLoop::TimedSource === 00218 class EventLoop::TimedSource : public virtual EventLoop::Source 00219 { 00220 uint64 expiration_usecs_; 00221 uint interval_msecs_; 00222 bool first_interval_; 00223 const bool oneshot_; 00224 union { 00225 BoolSlot bool_slot_; 00226 VoidSlot void_slot_; 00227 }; 00228 protected: 00229 virtual ~TimedSource (); 00230 virtual bool prepare (const State &state, 00231 int64 *timeout_usecs_p); 00232 virtual bool check (const State &state); 00233 virtual bool dispatch (const State &state); 00234 public: 00235 explicit TimedSource (const BoolSlot &slot, uint initial_interval_msecs = 0, uint repeat_interval_msecs = 0); 00236 explicit TimedSource (const VoidSlot &slot, uint initial_interval_msecs = 0, uint repeat_interval_msecs = 0); 00237 }; 00238 00239 // === EventLoop::PollFDSource === 00240 class EventLoop::PollFDSource : public virtual EventLoop::Source 00241 { 00242 protected: 00243 void construct (const String &mode); 00244 virtual ~PollFDSource (); 00245 virtual bool prepare (const State &state, 00246 int64 *timeout_usecs_p); 00247 virtual bool check (const State &state); 00248 virtual bool dispatch (const State &state); 00249 virtual void destroy (); 00250 PollFD pfd_; 00251 uint ignore_errors_ : 1; // 'E' 00252 uint ignore_hangup_ : 1; // 'H' 00253 uint never_close_ : 1; // 'C' 00254 private: 00255 const uint oneshot_ : 1; 00256 union { 00257 BPfdSlot bool_poll_slot_; 00258 VPfdSlot void_poll_slot_; 00259 }; 00260 public: 00261 explicit PollFDSource (const BPfdSlot &slot, int fd, const String &mode); 00262 explicit PollFDSource (const VPfdSlot &slot, int fd, const String &mode); 00263 }; 00264 00265 // === EventLoop methods === 00266 template<class BoolVoidFunctor> uint 00267 EventLoop::exec_now (BoolVoidFunctor &&bvf) 00268 { 00269 typedef decltype (bvf()) ReturnType; 00270 std::function<ReturnType()> slot (bvf); 00271 TimedSource *tsource = new TimedSource (slot); 00272 tsource->primary (true); 00273 return add (tsource, PRIORITY_NOW); 00274 } 00275 00276 template<class BoolVoidFunctor> uint 00277 EventLoop::exec_next (BoolVoidFunctor &&bvf) 00278 { 00279 typedef decltype (bvf()) ReturnType; 00280 std::function<ReturnType()> slot (bvf); 00281 return add (new TimedSource (slot), PRIORITY_NEXT); 00282 } 00283 00284 template<class BoolVoidFunctor> uint 00285 EventLoop::exec_notify (BoolVoidFunctor &&bvf) 00286 { 00287 typedef decltype (bvf()) ReturnType; 00288 std::function<ReturnType()> slot (bvf); 00289 return add (new TimedSource (slot), PRIORITY_NOTIFY); 00290 } 00291 00292 template<class BoolVoidFunctor> uint 00293 EventLoop::exec_normal (BoolVoidFunctor &&bvf) 00294 { 00295 typedef decltype (bvf()) ReturnType; 00296 std::function<ReturnType()> slot (bvf); 00297 return add (new TimedSource (slot), PRIORITY_NORMAL); 00298 } 00299 00300 template<class BoolVoidFunctor> uint 00301 EventLoop::exec_update (BoolVoidFunctor &&bvf) 00302 { 00303 typedef decltype (bvf()) ReturnType; 00304 std::function<ReturnType()> slot (bvf); 00305 return add (new TimedSource (slot), PRIORITY_UPDATE); 00306 } 00307 00308 template<class BoolVoidFunctor> uint 00309 EventLoop::exec_background (BoolVoidFunctor &&bvf) 00310 { 00311 typedef decltype (bvf()) ReturnType; 00312 std::function<ReturnType()> slot (bvf); 00313 return add (new TimedSource (slot), PRIORITY_BACKGROUND); 00314 } 00315 00316 inline uint 00317 EventLoop::exec_dispatcher (const DispatcherSlot &slot, int priority) 00318 { 00319 return add (new DispatcherSource (slot), priority); 00320 } 00321 00322 template<class BoolVoidFunctor> uint 00323 EventLoop::exec_timer (uint timeout_ms, BoolVoidFunctor &&bvf, int priority) 00324 { 00325 typedef decltype (bvf()) ReturnType; 00326 std::function<ReturnType()> slot (bvf); 00327 return add (new TimedSource (slot, timeout_ms, timeout_ms), priority); 00328 } 00329 00330 template<class BoolVoidFunctor> uint 00331 EventLoop::exec_timer (uint initial_timeout_ms, uint repeat_timeout_ms, BoolVoidFunctor &&bvf, int priority) 00332 { 00333 typedef decltype (bvf()) ReturnType; 00334 std::function<ReturnType()> slot (bvf); 00335 return add (new TimedSource (slot, initial_timeout_ms, repeat_timeout_ms), priority); 00336 } 00337 00338 template<class BoolVoidPollFunctor> uint 00339 EventLoop::exec_io_handler (BoolVoidPollFunctor &&bvf, int fd, const String &mode, int priority) 00340 { 00341 typedef decltype (bvf (*(PollFD*) 0)) ReturnType; 00342 std::function<ReturnType (PollFD&)> slot (bvf); 00343 return add (new PollFDSource (slot, fd, mode), priority); 00344 } 00345 00346 } // Rapicorn 00347 00348 #endif /* __RAPICORN_LOOP_HH__ */