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