| 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 |