OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/utility/run_loop.h" | 5 #include "mojo/public/cpp/utility/run_loop.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "mojo/public/cpp/utility/lib/thread_local.h" | 12 #include "mojo/public/cpp/utility/lib/thread_local.h" |
13 #include "mojo/public/cpp/utility/run_loop_handler.h" | 13 #include "mojo/public/cpp/utility/run_loop_handler.h" |
14 | 14 |
15 namespace mojo { | 15 namespace mojo { |
16 namespace { | 16 namespace { |
17 | 17 |
18 internal::ThreadLocalPointer<RunLoop> current_run_loop; | 18 internal::ThreadLocalPointer<RunLoop> current_run_loop; |
19 | 19 |
20 const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0); | 20 const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0); |
21 | 21 |
22 } // namespace | 22 } // namespace |
23 | 23 |
24 // State needed for one iteration of WaitMany(). | 24 // State needed for one iteration of WaitMany(). |
25 struct RunLoop::WaitState { | 25 struct RunLoop::WaitState { |
26 WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {} | 26 WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {} |
27 | 27 |
28 std::vector<Handle> handles; | 28 std::vector<Handle> handles; |
29 std::vector<MojoWaitFlags> wait_flags; | 29 std::vector<MojoHandleSignals> handle_signals; |
30 MojoDeadline deadline; | 30 MojoDeadline deadline; |
31 }; | 31 }; |
32 | 32 |
33 struct RunLoop::RunState { | 33 struct RunLoop::RunState { |
34 RunState() : should_quit(false) {} | 34 RunState() : should_quit(false) {} |
35 | 35 |
36 bool should_quit; | 36 bool should_quit; |
37 }; | 37 }; |
38 | 38 |
39 RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) { | 39 RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) { |
(...skipping 17 matching lines...) Expand all Loading... |
57 current_run_loop.Free(); | 57 current_run_loop.Free(); |
58 } | 58 } |
59 | 59 |
60 // static | 60 // static |
61 RunLoop* RunLoop::current() { | 61 RunLoop* RunLoop::current() { |
62 return current_run_loop.Get(); | 62 return current_run_loop.Get(); |
63 } | 63 } |
64 | 64 |
65 void RunLoop::AddHandler(RunLoopHandler* handler, | 65 void RunLoop::AddHandler(RunLoopHandler* handler, |
66 const Handle& handle, | 66 const Handle& handle, |
67 MojoWaitFlags wait_flags, | 67 MojoHandleSignals handle_signals, |
68 MojoDeadline deadline) { | 68 MojoDeadline deadline) { |
69 assert(current() == this); | 69 assert(current() == this); |
70 assert(handler); | 70 assert(handler); |
71 assert(handle.is_valid()); | 71 assert(handle.is_valid()); |
72 // Assume it's an error if someone tries to reregister an existing handle. | 72 // Assume it's an error if someone tries to reregister an existing handle. |
73 assert(0u == handler_data_.count(handle)); | 73 assert(0u == handler_data_.count(handle)); |
74 HandlerData handler_data; | 74 HandlerData handler_data; |
75 handler_data.handler = handler; | 75 handler_data.handler = handler; |
76 handler_data.wait_flags = wait_flags; | 76 handler_data.handle_signals = handle_signals; |
77 handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ? | 77 handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ? |
78 kInvalidTimeTicks : | 78 kInvalidTimeTicks : |
79 GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline); | 79 GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline); |
80 handler_data.id = next_handler_id_++; | 80 handler_data.id = next_handler_id_++; |
81 handler_data_[handle] = handler_data; | 81 handler_data_[handle] = handler_data; |
82 } | 82 } |
83 | 83 |
84 void RunLoop::RemoveHandler(const Handle& handle) { | 84 void RunLoop::RemoveHandler(const Handle& handle) { |
85 assert(current() == this); | 85 assert(current() == this); |
86 handler_data_.erase(handle); | 86 handler_data_.erase(handle); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 run_state_->should_quit = true; | 118 run_state_->should_quit = true; |
119 } | 119 } |
120 | 120 |
121 bool RunLoop::Wait(bool non_blocking) { | 121 bool RunLoop::Wait(bool non_blocking) { |
122 const WaitState wait_state = GetWaitState(non_blocking); | 122 const WaitState wait_state = GetWaitState(non_blocking); |
123 if (wait_state.handles.empty()) { | 123 if (wait_state.handles.empty()) { |
124 Quit(); | 124 Quit(); |
125 return false; | 125 return false; |
126 } | 126 } |
127 | 127 |
128 const MojoResult result = | 128 const MojoResult result = WaitMany(wait_state.handles, |
129 WaitMany(wait_state.handles, wait_state.wait_flags, wait_state.deadline); | 129 wait_state.handle_signals, |
| 130 wait_state.deadline); |
130 if (result >= 0) { | 131 if (result >= 0) { |
131 const size_t index = static_cast<size_t>(result); | 132 const size_t index = static_cast<size_t>(result); |
132 assert(handler_data_.find(wait_state.handles[index]) != | 133 assert(handler_data_.find(wait_state.handles[index]) != |
133 handler_data_.end()); | 134 handler_data_.end()); |
134 handler_data_[wait_state.handles[index]].handler->OnHandleReady( | 135 handler_data_[wait_state.handles[index]].handler->OnHandleReady( |
135 wait_state.handles[index]); | 136 wait_state.handles[index]); |
136 return true; | 137 return true; |
137 } | 138 } |
138 | 139 |
139 switch (result) { | 140 switch (result) { |
(...skipping 28 matching lines...) Expand all Loading... |
168 notified = true; | 169 notified = true; |
169 } | 170 } |
170 } | 171 } |
171 | 172 |
172 return notified; | 173 return notified; |
173 } | 174 } |
174 | 175 |
175 bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) { | 176 bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) { |
176 for (size_t i = 0; i < wait_state.handles.size(); ++i) { | 177 for (size_t i = 0; i < wait_state.handles.size(); ++i) { |
177 const MojoResult result = | 178 const MojoResult result = |
178 mojo::Wait(wait_state.handles[i], wait_state.wait_flags[i], | 179 mojo::Wait(wait_state.handles[i], wait_state.handle_signals[i], |
179 static_cast<MojoDeadline>(0)); | 180 static_cast<MojoDeadline>(0)); |
180 if (result == MOJO_RESULT_INVALID_ARGUMENT || | 181 if (result == MOJO_RESULT_INVALID_ARGUMENT || |
181 result == MOJO_RESULT_FAILED_PRECONDITION) { | 182 result == MOJO_RESULT_FAILED_PRECONDITION) { |
182 // Remove the handle first, this way if OnHandleError() tries to remove | 183 // Remove the handle first, this way if OnHandleError() tries to remove |
183 // the handle our iterator isn't invalidated. | 184 // the handle our iterator isn't invalidated. |
184 assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end()); | 185 assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end()); |
185 RunLoopHandler* handler = | 186 RunLoopHandler* handler = |
186 handler_data_[wait_state.handles[i]].handler; | 187 handler_data_[wait_state.handles[i]].handler; |
187 handler_data_.erase(wait_state.handles[i]); | 188 handler_data_.erase(wait_state.handles[i]); |
188 handler->OnHandleError(wait_state.handles[i], result); | 189 handler->OnHandleError(wait_state.handles[i], result); |
189 return true; | 190 return true; |
190 } | 191 } |
191 assert(MOJO_RESULT_DEADLINE_EXCEEDED == result); | 192 assert(MOJO_RESULT_DEADLINE_EXCEEDED == result); |
192 } | 193 } |
193 return false; | 194 return false; |
194 } | 195 } |
195 | 196 |
196 RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const { | 197 RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const { |
197 WaitState wait_state; | 198 WaitState wait_state; |
198 MojoTimeTicks min_time = kInvalidTimeTicks; | 199 MojoTimeTicks min_time = kInvalidTimeTicks; |
199 for (HandleToHandlerData::const_iterator i = handler_data_.begin(); | 200 for (HandleToHandlerData::const_iterator i = handler_data_.begin(); |
200 i != handler_data_.end(); ++i) { | 201 i != handler_data_.end(); ++i) { |
201 wait_state.handles.push_back(i->first); | 202 wait_state.handles.push_back(i->first); |
202 wait_state.wait_flags.push_back(i->second.wait_flags); | 203 wait_state.handle_signals.push_back(i->second.handle_signals); |
203 if (!non_blocking && i->second.deadline != kInvalidTimeTicks && | 204 if (!non_blocking && i->second.deadline != kInvalidTimeTicks && |
204 (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) { | 205 (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) { |
205 min_time = i->second.deadline; | 206 min_time = i->second.deadline; |
206 } | 207 } |
207 } | 208 } |
208 if (non_blocking) { | 209 if (non_blocking) { |
209 wait_state.deadline = static_cast<MojoDeadline>(0); | 210 wait_state.deadline = static_cast<MojoDeadline>(0); |
210 } else if (min_time != kInvalidTimeTicks) { | 211 } else if (min_time != kInvalidTimeTicks) { |
211 const MojoTimeTicks now = GetTimeTicksNow(); | 212 const MojoTimeTicks now = GetTimeTicksNow(); |
212 if (min_time < now) | 213 if (min_time < now) |
213 wait_state.deadline = static_cast<MojoDeadline>(0); | 214 wait_state.deadline = static_cast<MojoDeadline>(0); |
214 else | 215 else |
215 wait_state.deadline = static_cast<MojoDeadline>(min_time - now); | 216 wait_state.deadline = static_cast<MojoDeadline>(min_time - now); |
216 } | 217 } |
217 return wait_state; | 218 return wait_state; |
218 } | 219 } |
219 | 220 |
220 } // namespace mojo | 221 } // namespace mojo |
OLD | NEW |