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

Side by Side Diff: mojo/edk/system/wait_set_dispatcher.cc

Issue 1585493002: [mojo] Ports EDK (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/edk/system/wait_set_dispatcher.h" 5 #include "mojo/edk/system/wait_set_dispatcher.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <utility> 10 #include <utility>
(...skipping 21 matching lines...) Expand all
32 WaitSetDispatcher* const dispatcher_; 32 WaitSetDispatcher* const dispatcher_;
33 }; 33 };
34 34
35 WaitSetDispatcher::WaitState::WaitState() {} 35 WaitSetDispatcher::WaitState::WaitState() {}
36 36
37 WaitSetDispatcher::WaitState::~WaitState() {} 37 WaitSetDispatcher::WaitState::~WaitState() {}
38 38
39 WaitSetDispatcher::WaitSetDispatcher() 39 WaitSetDispatcher::WaitSetDispatcher()
40 : waiter_(new WaitSetDispatcher::Waiter(this)) {} 40 : waiter_(new WaitSetDispatcher::Waiter(this)) {}
41 41
42 WaitSetDispatcher::~WaitSetDispatcher() {
43 DCHECK(waiting_dispatchers_.empty());
44 DCHECK(awoken_queue_.empty());
45 DCHECK(processed_dispatchers_.empty());
46 }
47
48 Dispatcher::Type WaitSetDispatcher::GetType() const { 42 Dispatcher::Type WaitSetDispatcher::GetType() const {
49 return Type::WAIT_SET; 43 return Type::WAIT_SET;
50 } 44 }
51 45
52 void WaitSetDispatcher::CloseImplNoLock() { 46 MojoResult WaitSetDispatcher::Close() {
53 lock().AssertAcquired(); 47 {
54 for (const auto& entry : waiting_dispatchers_) 48 base::AutoLock lock(lock_);
Anand Mistry (off Chromium) 2016/01/28 02:26:25 Why not just hold lock_ for the entire function. I
55 entry.second.dispatcher->RemoveAwakable(waiter_.get(), nullptr); 49 if (is_closed_)
56 waiting_dispatchers_.clear(); 50 return MOJO_RESULT_INVALID_ARGUMENT;
51 is_closed_ = true;
52 }
53
54 {
55 base::AutoLock locker(awakable_lock_);
56 awakable_list_.CancelAll();
57 }
58
59 {
60 base::AutoLock lock(lock_);
61 for (const auto& entry : waiting_dispatchers_)
62 entry.second.dispatcher->RemoveAwakable(waiter_.get(), nullptr);
63 waiting_dispatchers_.clear();
64 }
57 65
58 base::AutoLock locker(awoken_lock_); 66 base::AutoLock locker(awoken_lock_);
59 awoken_queue_.clear(); 67 awoken_queue_.clear();
60 processed_dispatchers_.clear(); 68 processed_dispatchers_.clear();
69
70 return MOJO_RESULT_OK;
61 } 71 }
62 72
63 MojoResult WaitSetDispatcher::AddWaitingDispatcherImplNoLock( 73 MojoResult WaitSetDispatcher::AddWaitingDispatcher(
64 const scoped_refptr<Dispatcher>& dispatcher, 74 const scoped_refptr<Dispatcher>& dispatcher,
65 MojoHandleSignals signals, 75 MojoHandleSignals signals,
66 uintptr_t context) { 76 uintptr_t context) {
67 lock().AssertAcquired();
68 if (dispatcher == this) 77 if (dispatcher == this)
69 return MOJO_RESULT_INVALID_ARGUMENT; 78 return MOJO_RESULT_INVALID_ARGUMENT;
70 79
80 base::AutoLock lock(lock_);
81
82 if (is_closed_)
83 return MOJO_RESULT_INVALID_ARGUMENT;
84
71 uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get()); 85 uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get());
72 auto it = waiting_dispatchers_.find(dispatcher_handle); 86 auto it = waiting_dispatchers_.find(dispatcher_handle);
73 if (it != waiting_dispatchers_.end()) { 87 if (it != waiting_dispatchers_.end()) {
74 return MOJO_RESULT_ALREADY_EXISTS; 88 return MOJO_RESULT_ALREADY_EXISTS;
75 } 89 }
76 90
77 const MojoResult result = dispatcher->AddAwakable(waiter_.get(), signals, 91 const MojoResult result = dispatcher->AddAwakable(waiter_.get(), signals,
78 dispatcher_handle, nullptr); 92 dispatcher_handle, nullptr);
79 if (result == MOJO_RESULT_INVALID_ARGUMENT) { 93 if (result == MOJO_RESULT_INVALID_ARGUMENT) {
80 // Dispatcher is closed. 94 // Dispatcher is closed.
81 return result; 95 return result;
82 } else if (result != MOJO_RESULT_OK) { 96 } else if (result != MOJO_RESULT_OK) {
83 WakeDispatcher(result, dispatcher_handle); 97 WakeDispatcher(result, dispatcher_handle);
84 } 98 }
85 99
86 WaitState state; 100 WaitState state;
87 state.dispatcher = dispatcher; 101 state.dispatcher = dispatcher;
88 state.context = context; 102 state.context = context;
89 state.signals = signals; 103 state.signals = signals;
90 bool inserted = waiting_dispatchers_.insert( 104 bool inserted = waiting_dispatchers_.insert(
91 std::make_pair(dispatcher_handle, state)).second; 105 std::make_pair(dispatcher_handle, state)).second;
92 DCHECK(inserted); 106 DCHECK(inserted);
93 107
94 return MOJO_RESULT_OK; 108 return MOJO_RESULT_OK;
95 } 109 }
96 110
97 MojoResult WaitSetDispatcher::RemoveWaitingDispatcherImplNoLock( 111 MojoResult WaitSetDispatcher::RemoveWaitingDispatcher(
98 const scoped_refptr<Dispatcher>& dispatcher) { 112 const scoped_refptr<Dispatcher>& dispatcher) {
99 lock().AssertAcquired();
100 uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get()); 113 uintptr_t dispatcher_handle = reinterpret_cast<uintptr_t>(dispatcher.get());
101 auto it = waiting_dispatchers_.find(dispatcher_handle); 114 {
102 if (it == waiting_dispatchers_.end()) 115 base::AutoLock lock(lock_);
Anand Mistry (off Chromium) 2016/01/28 02:26:25 Need to handle the closed state. This can return "
103 return MOJO_RESULT_NOT_FOUND; 116 auto it = waiting_dispatchers_.find(dispatcher_handle);
117 if (it == waiting_dispatchers_.end())
118 return MOJO_RESULT_NOT_FOUND;
104 119
105 dispatcher->RemoveAwakable(waiter_.get(), nullptr); 120 dispatcher->RemoveAwakable(waiter_.get(), nullptr);
106 // At this point, it should not be possible for |waiter_| to be woken with 121 // At this point, it should not be possible for |waiter_| to be woken with
107 // |dispatcher|. 122 // |dispatcher|.
108 waiting_dispatchers_.erase(it); 123 waiting_dispatchers_.erase(it);
124 }
109 125
110 base::AutoLock locker(awoken_lock_); 126 base::AutoLock locker(awoken_lock_);
111 int num_erased = 0; 127 int num_erased = 0;
112 for (auto it = awoken_queue_.begin(); it != awoken_queue_.end();) { 128 for (auto it = awoken_queue_.begin(); it != awoken_queue_.end();) {
113 if (it->first == dispatcher_handle) { 129 if (it->first == dispatcher_handle) {
114 it = awoken_queue_.erase(it); 130 it = awoken_queue_.erase(it);
115 num_erased++; 131 num_erased++;
116 } else { 132 } else {
117 ++it; 133 ++it;
118 } 134 }
119 } 135 }
120 // The dispatcher should only exist in the queue once. 136 // The dispatcher should only exist in the queue once.
121 DCHECK_LE(num_erased, 1); 137 DCHECK_LE(num_erased, 1);
122 processed_dispatchers_.erase( 138 processed_dispatchers_.erase(
123 std::remove(processed_dispatchers_.begin(), processed_dispatchers_.end(), 139 std::remove(processed_dispatchers_.begin(), processed_dispatchers_.end(),
124 dispatcher_handle), 140 dispatcher_handle),
125 processed_dispatchers_.end()); 141 processed_dispatchers_.end());
126 142
127 return MOJO_RESULT_OK; 143 return MOJO_RESULT_OK;
128 } 144 }
129 145
130 MojoResult WaitSetDispatcher::GetReadyDispatchersImplNoLock( 146 MojoResult WaitSetDispatcher::GetReadyDispatchers(
131 uint32_t* count, 147 uint32_t* count,
132 DispatcherVector* dispatchers, 148 DispatcherVector* dispatchers,
133 MojoResult* results, 149 MojoResult* results,
134 uintptr_t* contexts) { 150 uintptr_t* contexts) {
135 lock().AssertAcquired(); 151 base::AutoLock lock(lock_);
152
136 dispatchers->clear(); 153 dispatchers->clear();
137 154
138 // Re-queue any already retrieved dispatchers. These should be the dispatchers 155 // Re-queue any already retrieved dispatchers. These should be the dispatchers
139 // that were returned on the last call to this function. This loop is 156 // that were returned on the last call to this function. This loop is
140 // necessary to preserve the logically level-triggering behaviour of waiting 157 // necessary to preserve the logically level-triggering behaviour of waiting
141 // in Mojo. In particular, if no action is taken on a signal, that signal 158 // in Mojo. In particular, if no action is taken on a signal, that signal
142 // continues to be satisfied, and therefore a |MojoWait()| on that 159 // continues to be satisfied, and therefore a |MojoWait()| on that
143 // handle/signal continues to return immediately. 160 // handle/signal continues to return immediately.
144 std::deque<uintptr_t> pending; 161 std::deque<uintptr_t> pending;
145 { 162 {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 num_woken++; 215 num_woken++;
199 } 216 }
200 217
201 *count = num_woken; 218 *count = num_woken;
202 if (!num_woken) 219 if (!num_woken)
203 return MOJO_RESULT_SHOULD_WAIT; 220 return MOJO_RESULT_SHOULD_WAIT;
204 221
205 return MOJO_RESULT_OK; 222 return MOJO_RESULT_OK;
206 } 223 }
207 224
208 void WaitSetDispatcher::CancelAllAwakablesNoLock() { 225 HandleSignalsState WaitSetDispatcher::GetHandleSignalsState() const {
Anand Mistry (off Chromium) 2016/01/28 02:26:25 Need to handle the closed state. Without it, it's
209 lock().AssertAcquired(); 226 HandleSignalsState rv;
210 base::AutoLock locker(awakable_lock_); 227 rv.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE;
211 awakable_list_.CancelAll(); 228 base::AutoLock locker(awoken_lock_);
229 if (!awoken_queue_.empty() || !processed_dispatchers_.empty())
230 rv.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE;
231 return rv;
212 } 232 }
213 233
214 MojoResult WaitSetDispatcher::AddAwakableImplNoLock( 234 MojoResult WaitSetDispatcher::AddAwakable(Awakable* awakable,
215 Awakable* awakable, 235 MojoHandleSignals signals,
216 MojoHandleSignals signals, 236 uintptr_t context,
217 uintptr_t context, 237 HandleSignalsState* signals_state) {
218 HandleSignalsState* signals_state) { 238 HandleSignalsState state(GetHandleSignalsState());
219 lock().AssertAcquired();
220
221 HandleSignalsState state(GetHandleSignalsStateImplNoLock());
222 if (state.satisfies(signals)) { 239 if (state.satisfies(signals)) {
223 if (signals_state) 240 if (signals_state)
224 *signals_state = state; 241 *signals_state = state;
225 return MOJO_RESULT_ALREADY_EXISTS; 242 return MOJO_RESULT_ALREADY_EXISTS;
226 } 243 }
227 if (!state.can_satisfy(signals)) { 244 if (!state.can_satisfy(signals)) {
228 if (signals_state) 245 if (signals_state)
229 *signals_state = state; 246 *signals_state = state;
230 return MOJO_RESULT_FAILED_PRECONDITION; 247 return MOJO_RESULT_FAILED_PRECONDITION;
231 } 248 }
232 249
233 base::AutoLock locker(awakable_lock_); 250 base::AutoLock locker(awakable_lock_);
234 awakable_list_.Add(awakable, signals, context); 251 awakable_list_.Add(awakable, signals, context);
235 return MOJO_RESULT_OK; 252 return MOJO_RESULT_OK;
236 } 253 }
237 254
238 void WaitSetDispatcher::RemoveAwakableImplNoLock( 255 void WaitSetDispatcher::RemoveAwakable(Awakable* awakable,
239 Awakable* awakable, 256 HandleSignalsState* signals_state) {
240 HandleSignalsState* signals_state) {
241 lock().AssertAcquired();
242 base::AutoLock locker(awakable_lock_); 257 base::AutoLock locker(awakable_lock_);
243 awakable_list_.Remove(awakable); 258 awakable_list_.Remove(awakable);
244 if (signals_state) 259 if (signals_state)
245 *signals_state = GetHandleSignalsStateImplNoLock(); 260 *signals_state = GetHandleSignalsState();
246 } 261 }
247 262
248 HandleSignalsState WaitSetDispatcher::GetHandleSignalsStateImplNoLock() const { 263 bool WaitSetDispatcher::BeginTransit() {
249 lock().AssertAcquired(); 264 // You can't transfer wait sets!
250 HandleSignalsState rv; 265 return false;
251 rv.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE;
252 base::AutoLock locker(awoken_lock_);
253 if (!awoken_queue_.empty() || !processed_dispatchers_.empty())
254 rv.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE;
255 return rv;
256 } 266 }
257 267
258 scoped_refptr<Dispatcher> 268 WaitSetDispatcher::~WaitSetDispatcher() {
259 WaitSetDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { 269 DCHECK(waiting_dispatchers_.empty());
260 lock().AssertAcquired(); 270 DCHECK(awoken_queue_.empty());
261 LOG(ERROR) << "Attempting to serialize WaitSet"; 271 DCHECK(processed_dispatchers_.empty());
262 CloseImplNoLock();
263 return new WaitSetDispatcher();
264 } 272 }
265 273
266 void WaitSetDispatcher::WakeDispatcher(MojoResult result, uintptr_t context) { 274 void WaitSetDispatcher::WakeDispatcher(MojoResult result, uintptr_t context) {
267 { 275 {
268 base::AutoLock locker(awoken_lock_); 276 base::AutoLock locker(awoken_lock_);
269 277
270 if (result == MOJO_RESULT_ALREADY_EXISTS) 278 if (result == MOJO_RESULT_ALREADY_EXISTS)
271 result = MOJO_RESULT_OK; 279 result = MOJO_RESULT_OK;
272 280
273 awoken_queue_.push_back(std::make_pair(context, result)); 281 awoken_queue_.push_back(std::make_pair(context, result));
274 } 282 }
275 283
276 base::AutoLock locker(awakable_lock_); 284 base::AutoLock locker(awakable_lock_);
277 HandleSignalsState signals_state; 285 HandleSignalsState signals_state;
278 signals_state.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE; 286 signals_state.satisfiable_signals = MOJO_HANDLE_SIGNAL_READABLE;
279 signals_state.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE; 287 signals_state.satisfied_signals = MOJO_HANDLE_SIGNAL_READABLE;
280 awakable_list_.AwakeForStateChange(signals_state); 288 awakable_list_.AwakeForStateChange(signals_state);
281 } 289 }
282 290
283 } // namespace edk 291 } // namespace edk
284 } // namespace mojo 292 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698