Rapicorn - Experimental UI Toolkit - Source Code  13.07.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
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/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__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines