aboutsummaryrefslogtreecommitdiffstats
path: root/brillo/message_loops/message_loop.h
blob: e9f804ee05a4a39e10aaafa584a855db27a1f020 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2015 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_
#define LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_

#include <string>

#include <base/callback.h>
#include <base/location.h>
#include <base/time/time.h>
#include <brillo/brillo_export.h>

namespace brillo {

class BRILLO_EXPORT MessageLoop {
 public:
  virtual ~MessageLoop();

  // A unique task identifier used to refer to scheduled callbacks.
  using TaskId = uint64_t;

  // The kNullEventId is reserved for an invalid task and will never be used
  // to refer to a real task.
  static const TaskId kTaskIdNull;

  // Return the MessageLoop for the current thread. It is a fatal error to
  // request the current MessageLoop if SetAsCurrent() was not called on the
  // current thread. If you really need to, use ThreadHasCurrent() to check if
  // there is a current thread.
  static MessageLoop* current();

  // Return whether there is a MessageLoop in the current thread.
  static bool ThreadHasCurrent();

  // Set this message loop as the current thread main loop. Only one message
  // loop can be set at a time. Use ReleaseFromCurrent() to release it.
  void SetAsCurrent();

  // Release this instance from the current thread. This instance must have
  // been previously set with SetAsCurrent().
  void ReleaseFromCurrent();

  // Schedule a Closure |task| to be executed after a |delay|. Returns a task
  // identifier for the scheduled task that can be used to cancel the task
  // before it is fired by passing it to CancelTask().
  // In case of an error scheduling the task, the kTaskIdNull is returned.
  // Note that once the call is executed or canceled, the TaskId could be reused
  // at a later point.
  // This methond can only be called from the same thread running the main loop.
  virtual TaskId PostDelayedTask(const base::Location& from_here,
                                 const base::Closure& task,
                                 base::TimeDelta delay) = 0;
  // Variant without the Location for easier usage.
  TaskId PostDelayedTask(const base::Closure& task, base::TimeDelta delay) {
    return PostDelayedTask(base::Location(), task, delay);
  }

  // A convenience method to schedule a call with no delay.
  // This methond can only be called from the same thread running the main loop.
  TaskId PostTask(const base::Closure& task) {
    return PostDelayedTask(task, base::TimeDelta());
  }
  TaskId PostTask(const base::Location& from_here,
                  const base::Closure& task) {
    return PostDelayedTask(from_here, task, base::TimeDelta());
  }

  // Watch mode flag used to watch for file descriptors.
  enum WatchMode {
    kWatchRead,
    kWatchWrite,
  };

  // Watch a file descriptor |fd| for it to be ready to perform the operation
  // passed in |mode| without blocking. When that happens, the |task| closure
  // will be executed. If |persistent| is true, the file descriptor will
  // continue to be watched and |task| will continue to be called until the task
  // is canceled with CancelTask().
  // Returns the TaskId describing this task. In case of error, returns
  // kTaskIdNull.
  virtual TaskId WatchFileDescriptor(const base::Location& from_here,
                                     int fd,
                                     WatchMode mode,
                                     bool persistent,
                                     const base::Closure& task) = 0;

  // Convenience function to call WatchFileDescriptor() without a location.
  TaskId WatchFileDescriptor(int fd,
                             WatchMode mode,
                             bool persistent,
                             const base::Closure& task) {
    return WatchFileDescriptor(base::Location(), fd, mode, persistent, task);
  }

  // Cancel a scheduled task. Returns whether the task was canceled. For
  // example, if the callback was already executed (or is being executed) or was
  // already canceled this method will fail. Note that the TaskId can be reused
  // after it was executed or cancelled.
  virtual bool CancelTask(TaskId task_id) = 0;

  // ---------------------------------------------------------------------------
  // Methods used to run and stop the message loop.

  // Run one iteration of the message loop, dispatching up to one task. The
  // |may_block| tells whether this method is allowed to block waiting for a
  // task to be ready to run. Returns whether it ran a task. Note that even
  // if |may_block| is true, this method can return false immediately if there
  // are no more tasks registered.
  virtual bool RunOnce(bool may_block) = 0;

  // Run the main loop until there are no more registered tasks.
  virtual void Run();

  // Quit the running main loop immediately. This method will make the current
  // running Run() method to return right after the current task returns back
  // to the message loop without processing any other task.
  virtual void BreakLoop();

 protected:
  MessageLoop() = default;

 private:
  // Tells whether Run() should quit the message loop in the default
  // implementation.
  bool should_exit_ = false;

  DISALLOW_COPY_AND_ASSIGN(MessageLoop);
};

}  // namespace brillo

#endif  // LIBBRILLO_BRILLO_MESSAGE_LOOPS_MESSAGE_LOOP_H_