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 #include <queue> 10 11 #include "mojo/public/cpp/bindings/callback.h" 12 #include "mojo/public/cpp/system/core.h" 13 14 namespace mojo { 15 16 class RunLoopHandler; 17 18 class RunLoop { 19 public: 20 RunLoop(); 21 ~RunLoop(); 22 23 // Sets up state needed for RunLoop. This must be invoked before creating a 24 // RunLoop. 25 static void SetUp(); 26 27 // Cleans state created by Setup(). 28 static void TearDown(); 29 30 // Returns the RunLoop for the current thread. Returns NULL if not yet 31 // created. 32 static RunLoop* current(); 33 34 // Registers a RunLoopHandler for the specified handle. Only one handler can 35 // be registered for a specified handle. 36 void AddHandler(RunLoopHandler* handler, 37 const Handle& handle, 38 MojoHandleSignals handle_signals, 39 MojoDeadline deadline); 40 void RemoveHandler(const Handle& handle); 41 bool HasHandler(const Handle& handle) const; 42 43 // Runs the loop servicing handles and tasks as they are ready. This returns 44 // when Quit() is invoked, or there are no more handles nor tasks. 45 void Run(); 46 47 // Runs the loop servicing any handles and tasks that are ready. Does not wait 48 // for handles or tasks to become ready before returning. Returns early if 49 // Quit() is invoked. 50 void RunUntilIdle(); 51 52 void Quit(); 53 54 // Adds a task to be performed after delay has elapsed. Must be posted to the 55 // current thread's RunLoop. 56 void PostDelayedTask(const Closure& task, MojoTimeTicks delay); 57 58 private: 59 struct RunState; 60 struct WaitState; 61 62 // Contains the data needed to track a request to AddHandler(). 63 struct HandlerData { 64 HandlerData() 65 : handler(NULL), 66 handle_signals(MOJO_HANDLE_SIGNAL_NONE), 67 deadline(0), 68 id(0) {} 69 70 RunLoopHandler* handler; 71 MojoHandleSignals handle_signals; 72 MojoTimeTicks deadline; 73 // See description of |RunLoop::next_handler_id_| for details. 74 int id; 75 }; 76 77 typedef std::map<Handle, HandlerData> HandleToHandlerData; 78 79 // Used for NotifyHandlers to specify whether HandlerData's |deadline| 80 // should be checked prior to notifying. 81 enum CheckDeadline { 82 CHECK_DEADLINE, 83 IGNORE_DEADLINE 84 }; 85 86 // Mode of operation of the run loop. 87 enum RunMode { 88 UNTIL_EMPTY, 89 UNTIL_IDLE 90 }; 91 92 // Runs the loop servicing any handles and tasks that are ready. If 93 // |run_mode| is |UNTIL_IDLE|, does not wait for handles or tasks to become 94 // ready before returning. Returns early if Quit() is invoked. 95 void RunInternal(RunMode run_mode); 96 97 // Do one unit of delayed work, if eligible. Returns true is a task was run. 98 bool DoDelayedWork(); 99 100 // Waits for a handle to be ready or until the next task must be run. Returns 101 // after servicing at least one handle (or there are no more handles) unless 102 // a task must be run or |non_blocking| is true, in which case it will also 103 // return if no task is registered and servicing at least one handle would 104 // require blocking. Returns true if a RunLoopHandler was notified. 105 bool Wait(bool non_blocking); 106 107 // Notifies handlers of |error|. If |check| == CHECK_DEADLINE, this will 108 // only notify handlers whose deadline has expired and skips the rest. 109 // Returns true if a RunLoopHandler was notified. 110 bool NotifyHandlers(MojoResult error, CheckDeadline check); 111 112 // Removes the first invalid handle. This is called if MojoWaitMany() finds an 113 // invalid handle. Returns true if a RunLoopHandler was notified. 114 bool RemoveFirstInvalidHandle(const WaitState& wait_state); 115 116 // Returns the state needed to pass to WaitMany(). 117 WaitState GetWaitState(bool non_blocking) const; 118 119 HandleToHandlerData handler_data_; 120 121 // If non-NULL we're running (inside Run()). Member references a value on the 122 // stack. 123 RunState* run_state_; 124 125 // An ever increasing value assigned to each HandlerData::id. Used to detect 126 // uniqueness while notifying. That is, while notifying expired timers we copy 127 // |handler_data_| and only notify handlers whose id match. If the id does not 128 // match it means the handler was removed then added so that we shouldn't 129 // notify it. 130 int next_handler_id_; 131 132 struct PendingTask { 133 PendingTask(const Closure& task, 134 MojoTimeTicks runtime, 135 uint64_t sequence_number); 136 ~PendingTask(); 137 138 bool operator<(const PendingTask& other) const; 139 140 Closure task; 141 MojoTimeTicks run_time; 142 uint64_t sequence_number; 143 }; 144 // An ever increasing sequence number attached to each pending task in order 145 // to preserve relative order of tasks posted at the 'same' time. 146 uint64_t next_sequence_number_; 147 typedef std::priority_queue<PendingTask> DelayedTaskQueue; 148 DelayedTaskQueue delayed_tasks_; 149 150 MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop); 151 }; 152 153 } // namespace mojo 154 155 #endif // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_ 156