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

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

Issue 2088833003: Add different behavior to AwakableList for "persistent" vs "one-shot" awakables. (Closed) Base URL: https://github.com/domokit/mojo.git@work793_wait_set_4.5
Patch Set: Created 4 years, 6 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
« no previous file with comments | « mojo/edk/system/wait_set_dispatcher.h ('k') | mojo/edk/system/waiter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 <utility> 7 #include <utility>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "mojo/edk/system/configuration.h" 10 #include "mojo/edk/system/configuration.h"
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 dispatcher->RemoveAwakable(true, this, cookie, nullptr); 190 dispatcher->RemoveAwakable(true, this, cookie, nullptr);
191 } 191 }
192 return MOJO_RESULT_INVALID_ARGUMENT; 192 return MOJO_RESULT_INVALID_ARGUMENT;
193 } 193 }
194 194
195 DCHECK(entries_.find(cookie) != entries_.end()); 195 DCHECK(entries_.find(cookie) != entries_.end());
196 DCHECK_EQ(entries_[cookie].get(), entry); 196 DCHECK_EQ(entries_[cookie].get(), entry);
197 197
198 if (result == MOJO_RESULT_ALREADY_EXISTS) { 198 if (result == MOJO_RESULT_ALREADY_EXISTS) {
199 // It was added, but the wait condition is already satisfied. 199 // It was added, but the wait condition is already satisfied.
200 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::POSSIBLY_SATISFIED); 200 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::SATISFIED);
201 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { 201 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
202 // The condition is never-satisfiable. Leave a zombie entry (i.e., leave 202 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::UNSATISFIABLE);
203 // |dispatcher| null).
204 mutex().Unlock();
205 return MOJO_RESULT_OK;
206 } else if (result != MOJO_RESULT_OK) { 203 } else if (result != MOJO_RESULT_OK) {
207 size_t num_erased = entries_.erase(cookie); 204 size_t num_erased = entries_.erase(cookie);
208 DCHECK_EQ(num_erased, 1u); 205 DCHECK_EQ(num_erased, 1u);
209 mutex().Unlock(); 206 mutex().Unlock();
210 return result; 207 return result;
211 } 208 }
212 209
213 // Update the entry to actually have the dispatcher. 210 // Update the entry to actually have the dispatcher.
214 entry->dispatcher = std::move(dispatcher); 211 entry->dispatcher = std::move(dispatcher);
215 212
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
253 UserPointer<uint32_t> max_results) { 250 UserPointer<uint32_t> max_results) {
254 MutexLocker locker(&mutex()); 251 MutexLocker locker(&mutex());
255 if (is_closed_no_lock()) 252 if (is_closed_no_lock())
256 return MOJO_RESULT_INVALID_ARGUMENT; 253 return MOJO_RESULT_INVALID_ARGUMENT;
257 254
258 // TODO(vtl) 255 // TODO(vtl)
259 NOTIMPLEMENTED(); 256 NOTIMPLEMENTED();
260 return MOJO_RESULT_UNIMPLEMENTED; 257 return MOJO_RESULT_UNIMPLEMENTED;
261 } 258 }
262 259
263 bool WaitSetDispatcher::Awake(uint64_t context, 260 void WaitSetDispatcher::Awake(uint64_t context,
264 AwakeReason reason, 261 AwakeReason reason,
265 const HandleSignalsState& signals_state) { 262 const HandleSignalsState& signals_state) {
266 MutexLocker locker(&mutex()); 263 MutexLocker locker(&mutex());
267 264
268 if (is_closed_no_lock()) { 265 if (is_closed_no_lock()) {
269 // See |CloseImplNoLock()|: This case may occur while we're unlocked in 266 // See |CloseImplNoLock()|: This case may occur while we're unlocked in
270 // |CloseImplNoLock()| (after that, we will have been removed from all the 267 // |CloseImplNoLock()| (after that, we will have been removed from all the
271 // awakable lists, so |Awake()| should no longer be called). We may as well 268 // awakable lists, so |Awake()| should no longer be called).
272 // return false here, which will automatically remove ourselves from the 269 return;
273 // awakable list (|CloseImplNoLock()| will call |RemoveAwakable()| anyway,
274 // but that's OK).
275 return false;
276 } 270 }
277 271
278 auto it = entries_.find(context); 272 auto it = entries_.find(context);
279 DCHECK(it != entries_.end()); 273 DCHECK(it != entries_.end());
280 const auto& entry = it->second; 274 const auto& entry = it->second;
275 // We should only ever get at most one "closed" (cancelled).
276 DCHECK_NE(static_cast<int>(entry->trigger_state),
277 static_cast<int>(Entry::TriggerState::CLOSED));
281 switch (reason) { 278 switch (reason) {
282 case AwakeReason::SATISFIED: 279 case AwakeReason::SATISFIED:
283 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { 280 case AwakeReason::UNSATISFIABLE:
284 AddPossiblyTriggeredNoLock(entry.get(), 281 // We shouldn't see these since we're used as a persistent |Awakable|.
285 Entry::TriggerState::POSSIBLY_SATISFIED); 282 NOTREACHED();
283 // Fall through.
284 case AwakeReason::CHANGED:
285 if (signals_state.satisfies(entry->signals)) {
286 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) {
287 AddPossiblyTriggeredNoLock(entry.get(),
288 Entry::TriggerState::SATISFIED);
289 } else {
290 entry->trigger_state = Entry::TriggerState::SATISFIED;
291 }
292 } else if (!signals_state.can_satisfy(entry->signals)) {
293 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) {
294 AddPossiblyTriggeredNoLock(entry.get(),
295 Entry::TriggerState::UNSATISFIABLE);
296 } else {
297 entry->trigger_state = Entry::TriggerState::UNSATISFIABLE;
298 }
299 } else {
300 if (entry->trigger_state != Entry::TriggerState::NOT_TRIGGERED)
301 RemovePossiblyTriggeredNoLock(entry.get());
286 } 302 }
287 return true; 303 break;
288 case AwakeReason::UNSATISFIABLE:
289 // Never satisfiable.
290 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) {
291 AddPossiblyTriggeredNoLock(entry.get(),
292 Entry::TriggerState::NEVER_SATISFIABLE);
293 } else {
294 if (entry->trigger_state == Entry::TriggerState::POSSIBLY_SATISFIED) {
295 entry->trigger_state = Entry::TriggerState::NEVER_SATISFIABLE;
296 } else {
297 // It's possible to get repeated "never satisfiable" triggers, but we
298 // shouldn't get anything after "closed".
299 DCHECK_NE(static_cast<int>(entry->trigger_state),
300 static_cast<int>(Entry::TriggerState::CLOSED));
301 }
302 }
303 // Due to some action on some other thread, it may become satisfiable
304 // again, so continue to be awoken.
305 return true;
306 case AwakeReason::CANCELLED: 304 case AwakeReason::CANCELLED:
307 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { 305 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) {
308 AddPossiblyTriggeredNoLock(entry.get(), Entry::TriggerState::CLOSED); 306 AddPossiblyTriggeredNoLock(entry.get(), Entry::TriggerState::CLOSED);
309 } else { 307 } else {
310 // We should only ever get at most one "closed".
311 DCHECK_NE(static_cast<int>(entry->trigger_state),
312 static_cast<int>(Entry::TriggerState::CLOSED));
313 entry->trigger_state = Entry::TriggerState::CLOSED; 308 entry->trigger_state = Entry::TriggerState::CLOSED;
314 } 309 }
315 entry->dispatcher = nullptr; 310 entry->dispatcher = nullptr;
316 return false; 311 break;
317 } 312 }
318 return false;
319 } 313 }
320 314
321 void WaitSetDispatcher::AddPossiblyTriggeredNoLock( 315 void WaitSetDispatcher::AddPossiblyTriggeredNoLock(
322 Entry* entry, 316 Entry* entry,
323 Entry::TriggerState new_trigger_state) { 317 Entry::TriggerState new_trigger_state) {
324 DCHECK_EQ(static_cast<int>(entry->trigger_state), 318 DCHECK_EQ(static_cast<int>(entry->trigger_state),
325 static_cast<int>(Entry::TriggerState::NOT_TRIGGERED)); 319 static_cast<int>(Entry::TriggerState::NOT_TRIGGERED));
326 DCHECK(!entry->possibly_triggered_previous); 320 DCHECK(!entry->possibly_triggered_previous);
327 DCHECK(!entry->possibly_triggered_next); 321 DCHECK(!entry->possibly_triggered_next);
328 DCHECK_NE(static_cast<int>(new_trigger_state), 322 DCHECK_NE(static_cast<int>(new_trigger_state),
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 entry->possibly_triggered_next->possibly_triggered_previous = 360 entry->possibly_triggered_next->possibly_triggered_previous =
367 entry->possibly_triggered_previous; 361 entry->possibly_triggered_previous;
368 } 362 }
369 363
370 entry->possibly_triggered_previous = nullptr; 364 entry->possibly_triggered_previous = nullptr;
371 entry->possibly_triggered_next = nullptr; 365 entry->possibly_triggered_next = nullptr;
372 } 366 }
373 367
374 } // namespace system 368 } // namespace system
375 } // namespace mojo 369 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/wait_set_dispatcher.h ('k') | mojo/edk/system/waiter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698