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