• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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