1ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved.
2ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// Use of this source code is governed by a BSD-style license that can be
3ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo// found in the LICENSE file.
4ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
5fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
6fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
7ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
8ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <string>
9ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
10ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/callback.h>
11106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo#include <base/location.h>
12ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo#include <base/time/time.h>
139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/brillo_export.h>
14ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo {
16ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
179ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkoclass BRILLO_EXPORT MessageLoop {
18ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo public:
19ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  virtual ~MessageLoop();
20ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
21ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // A unique task identifier used to refer to scheduled callbacks.
22ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  using TaskId = uint64_t;
23ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
24ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // The kNullEventId is reserved for an invalid task and will never be used
25ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // to refer to a real task.
26ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  static const TaskId kTaskIdNull;
27ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
28000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  // Return the MessageLoop for the current thread. It is a fatal error to
29000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  // request the current MessageLoop if SetAsCurrent() was not called on the
30000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  // current thread. If you really need to, use ThreadHasCurrent() to check if
31000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  // there is a current thread.
32ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  static MessageLoop* current();
33ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
34000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  // Return whether there is a MessageLoop in the current thread.
35000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo  static bool ThreadHasCurrent();
36000726053bddc605a6c78b5dece37bcb2c67f291Alex Deymo
37ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Set this message loop as the current thread main loop. Only one message
38ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // loop can be set at a time. Use ReleaseFromCurrent() to release it.
39ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  void SetAsCurrent();
40ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
41ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Release this instance from the current thread. This instance must have
42ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // been previously set with SetAsCurrent().
43ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  void ReleaseFromCurrent();
44ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
45ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Schedule a Closure |task| to be executed after a |delay|. Returns a task
46ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // identifier for the scheduled task that can be used to cancel the task
47ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // before it is fired by passing it to CancelTask().
48ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // In case of an error scheduling the task, the kTaskIdNull is returned.
49ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Note that once the call is executed or canceled, the TaskId could be reused
50ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // at a later point.
51ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // This methond can only be called from the same thread running the main loop.
52106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  virtual TaskId PostDelayedTask(const tracked_objects::Location& from_here,
53a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                 const base::Closure& task,
54ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo                                 base::TimeDelta delay) = 0;
55106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  // Variant without the Location for easier usage.
569ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko  TaskId PostDelayedTask(const base::Closure& task, base::TimeDelta delay) {
57106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo    return PostDelayedTask(tracked_objects::Location(), task, delay);
58106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  }
59ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
60ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // A convenience method to schedule a call with no delay.
61ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // This methond can only be called from the same thread running the main loop.
62a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo  TaskId PostTask(const base::Closure& task) {
63ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo    return PostDelayedTask(task, base::TimeDelta());
64ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  }
65106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  TaskId PostTask(const tracked_objects::Location& from_here,
66a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                  const base::Closure& task) {
67106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo    return PostDelayedTask(from_here, task, base::TimeDelta());
68106edd138a59b2fa3856028baa15201d4f7f3ffdAlex Deymo  }
69ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
703845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // Watch mode flag used to watch for file descriptors.
713845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  enum WatchMode {
723845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    kWatchRead,
733845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    kWatchWrite,
743845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  };
753845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
763845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // Watch a file descriptor |fd| for it to be ready to perform the operation
773845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // passed in |mode| without blocking. When that happens, the |task| closure
783845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // will be executed. If |persistent| is true, the file descriptor will
793845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // continue to be watched and |task| will continue to be called until the task
803845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // is canceled with CancelTask().
813845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // Returns the TaskId describing this task. In case of error, returns
823845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // kTaskIdNull.
833845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  virtual TaskId WatchFileDescriptor(const tracked_objects::Location& from_here,
843845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                                     int fd,
853845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                                     WatchMode mode,
863845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                                     bool persistent,
87a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                                     const base::Closure& task) = 0;
883845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
893845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  // Convenience function to call WatchFileDescriptor() without a location.
903845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  TaskId WatchFileDescriptor(int fd,
913845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                             WatchMode mode,
923845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo                             bool persistent,
93a8632e4a671d44cffa7b1f079baa0b9fdb48c5e3Alex Deymo                             const base::Closure& task) {
943845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo    return WatchFileDescriptor(
953845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo        tracked_objects::Location(), fd, mode, persistent, task);
963845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo  }
973845c6dfdf6c1edb45271e691990c12ef92f77c7Alex Deymo
98ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Cancel a scheduled task. Returns whether the task was canceled. For
99ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // example, if the callback was already executed (or is being executed) or was
100ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // already canceled this method will fail. Note that the TaskId can be reused
101ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // after it was executed or cancelled.
102ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  virtual bool CancelTask(TaskId task_id) = 0;
103ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
104ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // ---------------------------------------------------------------------------
105ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Methods used to run and stop the message loop.
106ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
107ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Run one iteration of the message loop, dispatching up to one task. The
108ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // |may_block| tells whether this method is allowed to block waiting for a
109ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // task to be ready to run. Returns whether it ran a task. Note that even
110ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // if |may_block| is true, this method can return false immediately if there
111ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // are no more tasks registered.
112ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  virtual bool RunOnce(bool may_block) = 0;
113ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
114ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Run the main loop until there are no more registered tasks.
115ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  virtual void Run();
116ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
117ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Quit the running main loop immediately. This method will make the current
118ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // running Run() method to return right after the current task returns back
119ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // to the message loop without processing any other task.
120ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  virtual void BreakLoop();
121ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
122ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo protected:
123ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  MessageLoop() = default;
124ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
125ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo private:
126ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // Tells whether Run() should quit the message loop in the default
127ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  // implementation.
128ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  bool should_exit_ = false;
129ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
130ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo  DISALLOW_COPY_AND_ASSIGN(MessageLoop);
131ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo};
132ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
1339ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko}  // namespace brillo
134ef3955af0d6b1baa7df93604c2d47b9e5af4de43Alex Deymo
135fed60b0c640828b320f56293c8bebc43fd2b1da8Alex Vakulenko#endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
136