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

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

Issue 66193007: Implementation of MessagePump for Mojo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merge 2 trunk Created 7 years, 1 month 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') | mojo/common/message_pump_mojo_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include "mojo/common/message_pump_mojo.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/logging.h"
11 #include "mojo/common/message_pump_mojo_handler.h"
12 #include "mojo/common/scoped_message_pipe.h"
13
14 namespace mojo {
15 namespace common {
16
17 // State needed for one iteration of MojoWaitMany. The first handle and flags
18 // corresponds to that of the control pipe.
19 struct MessagePumpMojo::WaitState {
20 std::vector<MojoHandle> handles;
21 std::vector<MojoWaitFlags> wait_flags;
22 };
23
24 struct MessagePumpMojo::RunState {
25 public:
26 RunState() : should_quit(false) {}
27
28 MojoHandle read_handle() const { return control_pipe.handle_0(); }
29 MojoHandle write_handle() const { return control_pipe.handle_1(); }
30
31 base::TimeTicks delayed_work_time;
32
33 // Used to wake up WaitForWork().
34 ScopedMessagePipe control_pipe;
35
36 bool should_quit;
37 };
38
39 MessagePumpMojo::MessagePumpMojo() : run_state_(NULL) {
40 }
41
42 MessagePumpMojo::~MessagePumpMojo() {
43 }
44
45 void MessagePumpMojo::AddHandler(MessagePumpMojoHandler* handler,
46 MojoHandle handle,
47 MojoWaitFlags wait_flags) {
48 DCHECK(handler);
49 DCHECK_NE(MOJO_HANDLE_INVALID, handle);
50 handlers_[handle].handler = handler;
51 handlers_[handle].wait_flags = wait_flags;
52
53 SignalControlPipe();
54 }
55
56 void MessagePumpMojo::RemoveHandler(MojoHandle handle) {
57 handlers_.erase(handle);
58 SignalControlPipe();
59 }
60
61 void MessagePumpMojo::Run(Delegate* delegate) {
62 RunState* old_state = run_state_;
63 RunState run_state;
64 // TODO: better deal with error handling.
65 CHECK_NE(run_state.control_pipe.handle_0(), MOJO_HANDLE_INVALID);
66 CHECK_NE(run_state.control_pipe.handle_1(), MOJO_HANDLE_INVALID);
67 run_state_ = &run_state;
68 bool more_work_is_plausible = true;
69 for (;;) {
70 const bool block = !more_work_is_plausible;
71 DoInternalWork(block);
72
73 // There isn't a good way to know if there are more handles ready, we assume
74 // not.
75 more_work_is_plausible = false;
76
77 if (run_state.should_quit)
78 break;
79
80 more_work_is_plausible |= delegate->DoWork();
81 if (run_state.should_quit)
82 break;
83
84 more_work_is_plausible |= delegate->DoDelayedWork(
85 &run_state.delayed_work_time);
86 if (run_state.should_quit)
87 break;
88
89 if (more_work_is_plausible)
90 continue;
91
92 more_work_is_plausible = delegate->DoIdleWork();
93 if (run_state.should_quit)
94 break;
95 }
96 run_state_ = old_state;
97 }
98
99 void MessagePumpMojo::Quit() {
100 if (run_state_)
101 run_state_->should_quit = true;
102 }
103
104 void MessagePumpMojo::ScheduleWork() {
105 SignalControlPipe();
106 }
107
108 void MessagePumpMojo::ScheduleDelayedWork(
109 const base::TimeTicks& delayed_work_time) {
110 if (!run_state_)
111 return;
112 run_state_->delayed_work_time = delayed_work_time;
113 SignalControlPipe();
114 }
115
116 void MessagePumpMojo::DoInternalWork(bool block) {
117 MojoDeadline deadline;
118 if (block && !run_state_->delayed_work_time.is_null()) {
119 const base::TimeDelta delta = run_state_->delayed_work_time -
120 base::TimeTicks::Now();
121 deadline = std::max(static_cast<MojoDeadline>(0),
122 static_cast<MojoDeadline>(delta.InMicroseconds()));
123 } else {
124 deadline = 0;
125 }
126 const WaitState wait_state = GetWaitState();
127 const MojoResult result = MojoWaitMany(
128 &wait_state.handles.front(),
129 &wait_state.wait_flags.front(),
130 static_cast<uint32_t>(wait_state.handles.size()),
131 deadline);
132 if (result == 0) {
133 // Control pipe was written to.
134 uint32_t num_bytes = 0;
135 MojoReadMessage(run_state_->read_handle(), NULL, &num_bytes, NULL, 0,
136 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
137 } else if (result > 0) {
138 const size_t index = static_cast<size_t>(result);
139 DCHECK(handlers_.find(wait_state.handles[index]) != handlers_.end());
140 handlers_[wait_state.handles[index]].handler->OnHandleReady(
141 wait_state.handles[index]);
142 } else {
143 switch (result) {
144 case MOJO_RESULT_INVALID_ARGUMENT:
145 case MOJO_RESULT_FAILED_PRECONDITION:
146 RemoveFirstInvalidHandle(wait_state);
147 break;
148 case MOJO_RESULT_DEADLINE_EXCEEDED:
149 break;
150 default:
151 NOTREACHED();
152 }
153 }
154 }
155
156 void MessagePumpMojo::RemoveFirstInvalidHandle(const WaitState& wait_state) {
157 // TODO(sky): deal with control pipe going bad.
158 for (size_t i = 1; i < wait_state.handles.size(); ++i) {
159 const MojoResult result =
160 MojoWait(wait_state.handles[i], wait_state.wait_flags[i], 0);
161 if (result == MOJO_RESULT_INVALID_ARGUMENT ||
162 result == MOJO_RESULT_FAILED_PRECONDITION) {
163 DCHECK(handlers_.find(wait_state.handles[i]) != handlers_.end());
164 MessagePumpMojoHandler* handler =
165 handlers_[wait_state.handles[i]].handler;
166 handlers_.erase(wait_state.handles[i]);
167 handler->OnHandleError(wait_state.handles[i], result);
168 return;
169 } else {
170 DCHECK_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
171 }
172 }
173 }
174
175 void MessagePumpMojo::SignalControlPipe() {
176 if (!run_state_)
177 return;
178
179 // TODO(sky): deal with error?
180 MojoWriteMessage(run_state_->write_handle(), NULL, 0, NULL, 0,
181 MOJO_WRITE_MESSAGE_FLAG_NONE);
182 }
183
184 MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState() const {
185 WaitState wait_state;
186 wait_state.handles.push_back(run_state_->write_handle());
187 wait_state.wait_flags.push_back(MOJO_WAIT_FLAG_READABLE);
188
189 for (HandleToHandler::const_iterator i = handlers_.begin();
190 i != handlers_.end(); ++i) {
191 wait_state.handles.push_back(i->first);
192 wait_state.wait_flags.push_back(i->second.wait_flags);
193 }
194 return wait_state;
195 }
196
197 } // namespace common
198 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/common/message_pump_mojo.h ('k') | mojo/common/message_pump_mojo_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698