Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
loop.hh
Go to the documentation of this file.
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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines