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
AwakableList()16 AwakableList::AwakableList() {
17 }
18
~AwakableList()19 AwakableList::~AwakableList() {
20 DCHECK(awakables_.empty());
21 }
22
AwakeForStateChange(const HandleSignalsState & state)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
CancelAll()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
Add(Awakable * awakable,MojoHandleSignals signals,uintptr_t context)54 void AwakableList::Add(Awakable* awakable,
55 MojoHandleSignals signals,
56 uintptr_t context) {
57 awakables_.push_back(AwakeInfo(awakable, signals, context));
58 }
59
Remove(Awakable * awakable)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
AddWatcher(MojoHandleSignals signals,const Watcher::WatchCallback & callback,uintptr_t context,const HandleSignalsState & current_state)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
RemoveWatcher(uintptr_t context)82 MojoResult AwakableList::RemoveWatcher(uintptr_t context) {
83 return watchers_.Remove(context);
84 }
85
86 } // namespace edk
87 } // namespace mojo
88