Home | History | Annotate | Download | only in system
      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