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 #include <utility>
10 
11 #include <base/callback.h>
12 #include <base/location.h>
13 #include <base/time/time.h>
14 #include <brillo/brillo_export.h>
15 
16 namespace brillo {
17 
18 class BRILLO_EXPORT MessageLoop {
19  public:
20   virtual ~MessageLoop();
21 
22   // A unique task identifier used to refer to scheduled callbacks.
23   using TaskId = uint64_t;
24 
25   // The kNullEventId is reserved for an invalid task and will never be used
26   // to refer to a real task.
27   static const TaskId kTaskIdNull;
28 
29   // Return the MessageLoop for the current thread. It is a fatal error to
30   // request the current MessageLoop if SetAsCurrent() was not called on the
31   // current thread. If you really need to, use ThreadHasCurrent() to check if
32   // there is a current thread.
33   static MessageLoop* current();
34 
35   // Return whether there is a MessageLoop in the current thread.
36   static bool ThreadHasCurrent();
37 
38   // Set this message loop as the current thread main loop. Only one message
39   // loop can be set at a time. Use ReleaseFromCurrent() to release it.
40   void SetAsCurrent();
41 
42   // Release this instance from the current thread. This instance must have
43   // been previously set with SetAsCurrent().
44   void ReleaseFromCurrent();
45 
46   // Schedule a Closure |task| to be executed after a |delay|. Returns a task
47   // identifier for the scheduled task that can be used to cancel the task
48   // before it is fired by passing it to CancelTask().
49   // In case of an error scheduling the task, the kTaskIdNull is returned.
50   // Note that once the call is executed or canceled, the TaskId could be reused
51   // at a later point.
52   // This methond can only be called from the same thread running the main loop.
53   virtual TaskId PostDelayedTask(const base::Location& from_here,
54                                  base::OnceClosure task,
55                                  base::TimeDelta delay) = 0;
56   // Variant without the Location for easier usage.
PostDelayedTask(base::OnceClosure task,base::TimeDelta delay)57   TaskId PostDelayedTask(base::OnceClosure task, base::TimeDelta delay) {
58     return PostDelayedTask(base::Location(), std::move(task), delay);
59   }
60 
61   // A convenience method to schedule a call with no delay.
62   // This methond can only be called from the same thread running the main loop.
PostTask(base::OnceClosure task)63   TaskId PostTask(base::OnceClosure task) {
64     return PostDelayedTask(std::move(task), base::TimeDelta());
65   }
PostTask(const base::Location & from_here,base::OnceClosure task)66   TaskId PostTask(const base::Location& from_here, base::OnceClosure task) {
67     return PostDelayedTask(from_here, std::move(task), base::TimeDelta());
68   }
69 
70   // Cancel a scheduled task. Returns whether the task was canceled. For
71   // example, if the callback was already executed (or is being executed) or was
72   // already canceled this method will fail. Note that the TaskId can be reused
73   // after it was executed or cancelled.
74   virtual bool CancelTask(TaskId task_id) = 0;
75 
76   // ---------------------------------------------------------------------------
77   // Methods used to run and stop the message loop.
78 
79   // Run one iteration of the message loop, dispatching up to one task. The
80   // |may_block| tells whether this method is allowed to block waiting for a
81   // task to be ready to run. Returns whether it ran a task. Note that even
82   // if |may_block| is true, this method can return false immediately if there
83   // are no more tasks registered.
84   virtual bool RunOnce(bool may_block) = 0;
85 
86   // Run the main loop until there are no more registered tasks.
87   virtual void Run();
88 
89   // Quit the running main loop immediately. This method will make the current
90   // running Run() method to return right after the current task returns back
91   // to the message loop without processing any other task.
92   virtual void BreakLoop();
93 
94  protected:
95   MessageLoop() = default;
96 
97  private:
98   // Tells whether Run() should quit the message loop in the default
99   // implementation.
100   bool should_exit_ = false;
101 
102   DISALLOW_COPY_AND_ASSIGN(MessageLoop);
103 };
104 
105 }  // namespace brillo
106 
107 #endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
108