1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2013 The Chromium Authors. All rights reserved. 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file. 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/awakable_list.h" 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <algorithm> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/logging.h" 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/awakable.h" 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/handle_signals_state.h" 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk { 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezAwakableList::AwakableList() { 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezAwakableList::~AwakableList() { 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(awakables_.empty()); 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid AwakableList::AwakeForStateChange(const HandleSignalsState& state) { 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Instead of deleting elements in-place, swap them with the last element and 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // erase the elements from the end. 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto last = awakables_.end(); 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool keep = true; 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (state.satisfies(it->signals)) 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez keep = it->awakable->Awake(MOJO_RESULT_OK, it->context); 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else if (!state.can_satisfy(it->signals)) 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez keep = it->awakable->Awake(MOJO_RESULT_FAILED_PRECONDITION, it->context); 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!keep) { 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez --last; 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::swap(*it, *last); 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++it; 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez awakables_.erase(last, awakables_.end()); 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez watchers_.NotifyForStateChange(state); 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid AwakableList::CancelAll() { 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (AwakeInfoList::iterator it = awakables_.begin(); it != awakables_.end(); 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++it) { 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez it->awakable->Awake(MOJO_RESULT_CANCELLED, it->context); 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez awakables_.clear(); 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez watchers_.NotifyClosed(); 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid AwakableList::Add(Awakable* awakable, 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MojoHandleSignals signals, 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uintptr_t context) { 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez awakables_.push_back(AwakeInfo(awakable, signals, context)); 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid AwakableList::Remove(Awakable* awakable) { 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We allow a thread to wait on the same handle multiple times simultaneously, 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // so we need to scan the entire list and remove all occurrences of |waiter|. 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez auto last = awakables_.end(); 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (AwakeInfoList::iterator it = awakables_.begin(); it != last;) { 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it->awakable == awakable) { 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez --last; 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::swap(*it, *last); 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++it; 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez awakables_.erase(last, awakables_.end()); 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMojoResult AwakableList::AddWatcher(MojoHandleSignals signals, 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const Watcher::WatchCallback& callback, 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uintptr_t context, 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const HandleSignalsState& current_state) { 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return watchers_.Add(signals, callback, context, current_state); 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMojoResult AwakableList::RemoveWatcher(uintptr_t context) { 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return watchers_.Remove(context); 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace edk 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 88