Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: mojo/common/message_pump_mojo.cc

Issue 69883008: Implements HandleWatcher in terms of MessagePumpMojo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add id to detect whether should notify Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/common/message_pump_mojo.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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/common/message_pump_mojo.h" 5 #include "mojo/common/message_pump_mojo.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 19 matching lines...) Expand all
30 MojoHandle write_handle() const { return control_pipe.handle_1(); } 30 MojoHandle write_handle() const { return control_pipe.handle_1(); }
31 31
32 base::TimeTicks delayed_work_time; 32 base::TimeTicks delayed_work_time;
33 33
34 // Used to wake up WaitForWork(). 34 // Used to wake up WaitForWork().
35 ScopedMessagePipe control_pipe; 35 ScopedMessagePipe control_pipe;
36 36
37 bool should_quit; 37 bool should_quit;
38 }; 38 };
39 39
40 MessagePumpMojo::MessagePumpMojo() : run_state_(NULL) { 40 MessagePumpMojo::MessagePumpMojo() : run_state_(NULL), next_handler_id_(0) {
41 } 41 }
42 42
43 MessagePumpMojo::~MessagePumpMojo() { 43 MessagePumpMojo::~MessagePumpMojo() {
44 } 44 }
45 45
46 void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler, 46 void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler,
47 MojoHandle handle, 47 MojoHandle handle,
48 MojoWaitFlags wait_flags) { 48 MojoWaitFlags wait_flags,
49 base::TimeTicks deadline) {
49 DCHECK(handler); 50 DCHECK(handler);
50 DCHECK_NE(MOJO_HANDLE_INVALID, handle); 51 DCHECK_NE(MOJO_HANDLE_INVALID, handle);
51 handlers_[handle].handler = handler; 52 // Assume it's an error if someone tries to reregister an existing handle.
52 handlers_[handle].wait_flags = wait_flags; 53 DCHECK_EQ(0u, handlers_.count(handle));
53 54 Handler handler_data;
54 SignalControlPipe(); 55 handler_data.handler = handler;
56 handler_data.wait_flags = wait_flags;
57 handler_data.deadline = deadline;
58 handler_data.id = next_handler_id_++;
59 handlers_[handle] = handler_data;
55 } 60 }
56 61
57 void MessagePumpMojo::RemoveHandler(MojoHandle handle) { 62 void MessagePumpMojo::RemoveHandler(MojoHandle handle) {
58 handlers_.erase(handle); 63 handlers_.erase(handle);
59 SignalControlPipe();
60 } 64 }
61 65
62 void MessagePumpMojo::Run(Delegate* delegate) { 66 void MessagePumpMojo::Run(Delegate* delegate) {
63 RunState* old_state = run_state_; 67 RunState* old_state = run_state_;
64 RunState run_state; 68 RunState run_state;
65 // TODO: better deal with error handling. 69 // TODO: better deal with error handling.
66 CHECK_NE(run_state.control_pipe.handle_0(), MOJO_HANDLE_INVALID); 70 CHECK_NE(run_state.control_pipe.handle_0(), MOJO_HANDLE_INVALID);
67 CHECK_NE(run_state.control_pipe.handle_1(), MOJO_HANDLE_INVALID); 71 CHECK_NE(run_state.control_pipe.handle_1(), MOJO_HANDLE_INVALID);
68 run_state_ = &run_state; 72 run_state_ = &run_state;
69 bool more_work_is_plausible = true; 73 bool more_work_is_plausible = true;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 112
109 void MessagePumpMojo::ScheduleDelayedWork( 113 void MessagePumpMojo::ScheduleDelayedWork(
110 const base::TimeTicks& delayed_work_time) { 114 const base::TimeTicks& delayed_work_time) {
111 if (!run_state_) 115 if (!run_state_)
112 return; 116 return;
113 run_state_->delayed_work_time = delayed_work_time; 117 run_state_->delayed_work_time = delayed_work_time;
114 SignalControlPipe(); 118 SignalControlPipe();
115 } 119 }
116 120
117 void MessagePumpMojo::DoInternalWork(bool block) { 121 void MessagePumpMojo::DoInternalWork(bool block) {
118 MojoDeadline deadline; 122 const MojoDeadline deadline = block ? GetDeadlineForWait() : 0;
119 if (block && !run_state_->delayed_work_time.is_null()) {
120 const base::TimeDelta delta = run_state_->delayed_work_time -
121 base::TimeTicks::Now();
122 deadline = std::max(static_cast<MojoDeadline>(0),
123 static_cast<MojoDeadline>(delta.InMicroseconds()));
124 } else {
125 deadline = 0;
126 }
127 const WaitState wait_state = GetWaitState(); 123 const WaitState wait_state = GetWaitState();
128 const MojoResult result = MojoWaitMany( 124 const MojoResult result = MojoWaitMany(
129 &wait_state.handles.front(), 125 &wait_state.handles.front(),
130 &wait_state.wait_flags.front(), 126 &wait_state.wait_flags.front(),
131 static_cast<uint32_t>(wait_state.handles.size()), 127 static_cast<uint32_t>(wait_state.handles.size()),
132 deadline); 128 deadline);
133 if (result == 0) { 129 if (result == 0) {
134 // Control pipe was written to. 130 // Control pipe was written to.
135 uint32_t num_bytes = 0; 131 uint32_t num_bytes = 0;
136 MojoReadMessage(run_state_->read_handle(), NULL, &num_bytes, NULL, 0, 132 MojoReadMessage(run_state_->read_handle(), NULL, &num_bytes, NULL, 0,
137 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); 133 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
138 } else if (result > 0) { 134 } else if (result > 0) {
139 const size_t index = static_cast<size_t>(result); 135 const size_t index = static_cast<size_t>(result);
140 DCHECK(handlers_.find(wait_state.handles[index]) != handlers_.end()); 136 DCHECK(handlers_.find(wait_state.handles[index]) != handlers_.end());
141 handlers_[wait_state.handles[index]].handler->OnHandleReady( 137 handlers_[wait_state.handles[index]].handler->OnHandleReady(
142 wait_state.handles[index]); 138 wait_state.handles[index]);
143 } else { 139 } else {
144 switch (result) { 140 switch (result) {
145 case MOJO_RESULT_INVALID_ARGUMENT: 141 case MOJO_RESULT_INVALID_ARGUMENT:
146 case MOJO_RESULT_FAILED_PRECONDITION: 142 case MOJO_RESULT_FAILED_PRECONDITION:
147 RemoveFirstInvalidHandle(wait_state); 143 RemoveFirstInvalidHandle(wait_state);
148 break; 144 break;
149 case MOJO_RESULT_DEADLINE_EXCEEDED: 145 case MOJO_RESULT_DEADLINE_EXCEEDED:
150 break; 146 break;
151 default: 147 default:
152 NOTREACHED(); 148 NOTREACHED();
153 } 149 }
154 } 150 }
151
152 // Notify and remove any handlers whose time has expired. Make a copy in case
153 // someone tries to add/remove new handlers from notification.
154 const HandleToHandler cloned_handlers(handlers_);
155 const base::TimeTicks now(base::TimeTicks::Now());
156 for (HandleToHandler::const_iterator i = cloned_handlers.begin();
157 i != cloned_handlers.end(); ++i) {
158 // Since we're iterating over a clone of the handlers, verify the handler is
159 // still valid before notifying.
160 if (!i->second.deadline.is_null() && i->second.deadline < now &&
161 handlers_.find(i->first) != handlers_.end() &&
162 handlers_[i->first].id == i->second.id) {
163 i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED);
164 }
165 }
155 } 166 }
156 167
157 void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) { 168 void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) {
158 // TODO(sky): deal with control pipe going bad. 169 // TODO(sky): deal with control pipe going bad.
159 for (size_t i = 1; i < wait_state.handles.size(); ++i) { 170 for (size_t i = 1; i < wait_state.handles.size(); ++i) {
160 const MojoResult result = 171 const MojoResult result =
161 MojoWait(wait_state.handles[i], wait_state.wait_flags[i], 0); 172 MojoWait(wait_state.handles[i], wait_state.wait_flags[i], 0);
162 if (result == MOJO_RESULT_INVALID_ARGUMENT || 173 if (result == MOJO_RESULT_INVALID_ARGUMENT ||
163 result == MOJO_RESULT_FAILED_PRECONDITION) { 174 result == MOJO_RESULT_FAILED_PRECONDITION) {
175 // Remove the handle first, this way if OnHandleError() tries to remove
176 // the handle our iterator isn't invalidated.
164 DCHECK(handlers_.find(wait_state.handles[i]) != handlers_.end()); 177 DCHECK(handlers_.find(wait_state.handles[i]) != handlers_.end());
165 MessagePumpMojoHandler* handler = 178 MessagePumpMojoHandler* handler =
166 handlers_[wait_state.handles[i]].handler; 179 handlers_[wait_state.handles[i]].handler;
167 handlers_.erase(wait_state.handles[i]); 180 handlers_.erase(wait_state.handles[i]);
168 handler->OnHandleError(wait_state.handles[i], result); 181 handler->OnHandleError(wait_state.handles[i], result);
169 return; 182 return;
170 } else { 183 } else {
171 DCHECK_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result); 184 DCHECK_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
172 } 185 }
173 } 186 }
(...skipping 14 matching lines...) Expand all
188 wait_state.wait_flags.push_back(MOJO_WAIT_FLAG_READABLE); 201 wait_state.wait_flags.push_back(MOJO_WAIT_FLAG_READABLE);
189 202
190 for (HandleToHandler::const_iterator i = handlers_.begin(); 203 for (HandleToHandler::const_iterator i = handlers_.begin();
191 i != handlers_.end(); ++i) { 204 i != handlers_.end(); ++i) {
192 wait_state.handles.push_back(i->first); 205 wait_state.handles.push_back(i->first);
193 wait_state.wait_flags.push_back(i->second.wait_flags); 206 wait_state.wait_flags.push_back(i->second.wait_flags);
194 } 207 }
195 return wait_state; 208 return wait_state;
196 } 209 }
197 210
211 MojoDeadline MessagePumpMojo::GetDeadlineForWait() const {
212 base::TimeTicks min_time = run_state_->delayed_work_time;
213 for (HandleToHandler::const_iterator i = handlers_.begin();
214 i != handlers_.end(); ++i) {
215 if (min_time.is_null() && i->second.deadline < min_time)
216 min_time = i->second.deadline;
217 }
218 return min_time.is_null() ? MOJO_DEADLINE_INDEFINITE :
219 std::max(static_cast<MojoDeadline>(0),
220 static_cast<MojoDeadline>(
221 (min_time - base::TimeTicks::Now()).InMicroseconds()));
222 }
223
198 } // namespace common 224 } // namespace common
199 } // namespace mojo 225 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/common/message_pump_mojo.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698