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.
PostDelayedTask(const base::Closure & task,base::TimeDelta delay)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.
PostTask(const base::Closure & task)62   TaskId PostTask(const base::Closure& task) {
63     return PostDelayedTask(task, base::TimeDelta());
64   }
PostTask(const tracked_objects::Location & from_here,const base::Closure & task)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.
WatchFileDescriptor(int fd,WatchMode mode,bool persistent,const base::Closure & task)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