run_loop.h revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1// Copyright 2013 The Chromium 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 MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
6#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
7
8#include <map>
9
10#include "mojo/public/cpp/system/core.h"
11
12namespace mojo {
13
14class RunLoopHandler;
15
16class RunLoop {
17 public:
18  RunLoop();
19  ~RunLoop();
20
21  // Sets up state needed for RunLoop. This must be invoked before creating a
22  // RunLoop.
23  static void SetUp();
24
25  // Cleans state created by Setup().
26  static void TearDown();
27
28  // Returns the RunLoop for the current thread. Returns NULL if not yet
29  // created.
30  static RunLoop* current();
31
32  // Registers a RunLoopHandler for the specified handle. Only one handler can
33  // be registered for a specified handle.
34  void AddHandler(RunLoopHandler* handler,
35                  const Handle& handle,
36                  MojoHandleSignals handle_signals,
37                  MojoDeadline deadline);
38  void RemoveHandler(const Handle& handle);
39  bool HasHandler(const Handle& handle) const;
40
41  // Runs the loop servicing handles as they are ready. This returns when Quit()
42  // is invoked, or there no more handles.
43  void Run();
44
45  // Runs the loop servicing any handles that are ready. Does not wait for
46  // handles to become ready before returning. Returns early if Quit() is
47  // invoked.
48  void RunUntilIdle();
49
50  void Quit();
51
52 private:
53  struct RunState;
54  struct WaitState;
55
56  // Contains the data needed to track a request to AddHandler().
57  struct HandlerData {
58    HandlerData()
59        : handler(NULL),
60          handle_signals(MOJO_HANDLE_SIGNAL_NONE),
61          deadline(0),
62          id(0) {}
63
64    RunLoopHandler* handler;
65    MojoHandleSignals handle_signals;
66    MojoTimeTicks deadline;
67    // See description of |RunLoop::next_handler_id_| for details.
68    int id;
69  };
70
71  typedef std::map<Handle, HandlerData> HandleToHandlerData;
72
73  // Waits for a handle to be ready. Returns after servicing at least one
74  // handle (or there are no more handles) unless |non_blocking| is true,
75  // in which case it will also return if servicing at least one handle
76  // would require blocking. Returns true if a RunLoopHandler was notified.
77  bool Wait(bool non_blocking);
78
79  // Notifies any handlers whose deadline has expired. Returns true if a
80  // RunLoopHandler was notified.
81  bool NotifyDeadlineExceeded();
82
83  // Removes the first invalid handle. This is called if MojoWaitMany() finds an
84  // invalid handle. Returns true if a RunLoopHandler was notified.
85  bool RemoveFirstInvalidHandle(const WaitState& wait_state);
86
87  // Returns the state needed to pass to WaitMany().
88  WaitState GetWaitState(bool non_blocking) const;
89
90  HandleToHandlerData handler_data_;
91
92  // If non-NULL we're running (inside Run()). Member references a value on the
93  // stack.
94  RunState* run_state_;
95
96  // An ever increasing value assigned to each HandlerData::id. Used to detect
97  // uniqueness while notifying. That is, while notifying expired timers we copy
98  // |handler_data_| and only notify handlers whose id match. If the id does not
99  // match it means the handler was removed then added so that we shouldn't
100  // notify it.
101  int next_handler_id_;
102
103  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop);
104};
105
106}  // namespace mojo
107
108#endif  // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
109