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/edk/system/awakable_list.h" 6 7 #include <algorithm> 8 9 #include "base/logging.h" 10 #include "mojo/edk/system/awakable.h" 11 #include "mojo/edk/system/handle_signals_state.h" 12 13 namespace mojo { 14 namespace edk { 15 16 AwakableList::AwakableList() { 17 } 18 19 AwakableList::~AwakableList() { 20 DCHECK(awakables_.empty()); 21 } 22 23 void AwakableList::AwakeForStateChange(const HandleSignalsState& state) { 24 // Instead of deleting elements in-place, swap them with the last element and 25 // erase the elements from the end. 26 auto last = awakables_.end(); 27 for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { 28 bool keep = true; 29 if (state.satisfies(it->signals)) 30 keep = it->awakable->Awake(MOJO_RESULT_OK, it->context); 31 else if (!state.can_satisfy(it->signals)) 32 keep = it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context); 33 34 if (!keep) { 35 --last; 36 std::swap(*it, *last); 37 } else { 38 ++it; 39 } 40 } 41 awakables_.erase(last, awakables_.end()); 42 watchers_.NotifyForStateChange(state); 43 } 44 45 void AwakableList::CancelAll() { 46 for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end(); 47 ++it) { 48 it->awakable->Awake(MOJO_RESULT_CANCELLED, it->context); 49 } 50 awakables_.clear(); 51 watchers_.NotifyClosed(); 52 } 53 54 void AwakableList::Add(Awakable* awakable, 55 MojoHandleSignals signals, 56 uintptr_t context) { 57 awakables_.push_back(AwakeInfo(awakable, signals, context)); 58 } 59 60 void AwakableList::Remove(Awakable* awakable) { 61 // We allow a thread to wait on the same handle multiple times simultaneously, 62 // so we need to scan the entire list and remove all occurrences of |waiter|. 63 auto last = awakables_.end(); 64 for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { 65 if (it->awakable == awakable) { 66 --last; 67 std::swap(*it, *last); 68 } else { 69 ++it; 70 } 71 } 72 awakables_.erase(last, awakables_.end()); 73 } 74 75 MojoResult AwakableList::AddWatcher(MojoHandleSignals signals, 76 const Watcher::WatchCallback& callback, 77 uintptr_t context, 78 const HandleSignalsState& current_state) { 79 return watchers_.Add(signals, callback, context, current_state); 80 } 81 82 MojoResult AwakableList::RemoveWatcher(uintptr_t context) { 83 return watchers_.Remove(context); 84 } 85 86 } // namespace edk 87 } // namespace mojo 88