Home | History | Annotate | Download | only in message_loops
      1 // Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
      6 #define LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
      7 
      8 #include <string>
      9 
     10 #include <base/callback.h>
     11 #include <base/location.h>
     12 #include <base/time/time.h>
     13 #include <brillo/brillo_export.h>
     14 
     15 namespace brillo {
     16 
     17 class BRILLO_EXPORT MessageLoop {
     18  public:
     19   virtual ~MessageLoop();
     20 
     21   // A unique task identifier used to refer to scheduled callbacks.
     22   using TaskId = uint64_t;
     23 
     24   // The kNullEventId is reserved for an invalid task and will never be used
     25   // to refer to a real task.
     26   static const TaskId kTaskIdNull;
     27 
     28   // Return the MessageLoop for the current thread. It is a fatal error to
     29   // request the current MessageLoop if SetAsCurrent() was not called on the
     30   // current thread. If you really need to, use ThreadHasCurrent() to check if
     31   // there is a current thread.
     32   static MessageLoop* current();
     33 
     34   // Return whether there is a MessageLoop in the current thread.
     35   static bool ThreadHasCurrent();
     36 
     37   // Set this message loop as the current thread main loop. Only one message
     38   // loop can be set at a time. Use ReleaseFromCurrent() to release it.
     39   void SetAsCurrent();
     40 
     41   // Release this instance from the current thread. This instance must have
     42   // been previously set with SetAsCurrent().
     43   void ReleaseFromCurrent();
     44 
     45   // Schedule a Closure |task| to be executed after a |delay|. Returns a task
     46   // identifier for the scheduled task that can be used to cancel the task
     47   // before it is fired by passing it to CancelTask().
     48   // In case of an error scheduling the task, the kTaskIdNull is returned.
     49   // Note that once the call is executed or canceled, the TaskId could be reused
     50   // at a later point.
     51   // This methond can only be called from the same thread running the main loop.
     52   virtual TaskId PostDelayedTask(const tracked_objects::Location& from_here,
     53                                  const base::Closure& task,
     54                                  base::TimeDelta delay) = 0;
     55   // Variant without the Location for easier usage.
     56   TaskId PostDelayedTask(const base::Closure& task, base::TimeDelta delay) {
     57     return PostDelayedTask(tracked_objects::Location(), task, delay);
     58   }
     59 
     60   // A convenience method to schedule a call with no delay.
     61   // This methond can only be called from the same thread running the main loop.
     62   TaskId PostTask(const base::Closure& task) {
     63     return PostDelayedTask(task, base::TimeDelta());
     64   }
     65   TaskId PostTask(const tracked_objects::Location& from_here,
     66                   const base::Closure& task) {
     67     return PostDelayedTask(from_here, task, base::TimeDelta());
     68   }
     69 
     70   // Watch mode flag used to watch for file descriptors.
     71   enum WatchMode {
     72     kWatchRead,
     73     kWatchWrite,
     74   };
     75 
     76   // Watch a file descriptor |fd| for it to be ready to perform the operation
     77   // passed in |mode| without blocking. When that happens, the |task| closure
     78   // will be executed. If |persistent| is true, the file descriptor will
     79   // continue to be watched and |task| will continue to be called until the task
     80   // is canceled with CancelTask().
     81   // Returns the TaskId describing this task. In case of error, returns
     82   // kTaskIdNull.
     83   virtual TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
     84                                      int fd,
     85                                      WatchMode mode,
     86                                      bool persistent,
     87                                      const base::Closure& task) = 0;
     88 
     89   // Convenience function to call WatchFileDescriptor() without a location.
     90   TaskId WatchFileDescriptor(int fd,
     91                              WatchMode mode,
     92                              bool persistent,
     93                              const base::Closure& task) {
     94     return WatchFileDescriptor(
     95         tracked_objects::Location(), fd, mode, persistent, task);
     96   }
     97 
     98   // Cancel a scheduled task. Returns whether the task was canceled. For
     99   // example, if the callback was already executed (or is being executed) or was
    100   // already canceled this method will fail. Note that the TaskId can be reused
    101   // after it was executed or cancelled.
    102   virtual bool CancelTask(TaskId task_id) = 0;
    103 
    104   // ---------------------------------------------------------------------------
    105   // Methods used to run and stop the message loop.
    106 
    107   // Run one iteration of the message loop, dispatching up to one task. The
    108   // |may_block| tells whether this method is allowed to block waiting for a
    109   // task to be ready to run. Returns whether it ran a task. Note that even
    110   // if |may_block| is true, this method can return false immediately if there
    111   // are no more tasks registered.
    112   virtual bool RunOnce(bool may_block) = 0;
    113 
    114   // Run the main loop until there are no more registered tasks.
    115   virtual void Run();
    116 
    117   // Quit the running main loop immediately. This method will make the current
    118   // running Run() method to return right after the current task returns back
    119   // to the message loop without processing any other task.
    120   virtual void BreakLoop();
    121 
    122  protected:
    123   MessageLoop() = default;
    124 
    125  private:
    126   // Tells whether Run() should quit the message loop in the default
    127   // implementation.
    128   bool should_exit_ = false;
    129 
    130   DISALLOW_COPY_AND_ASSIGN(MessageLoop);
    131 };
    132 
    133 }  // namespace brillo
    134 
    135 #endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
    136