1 // Copyright 2016 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/core/watcher_set.h"
6
7 #include <utility>
8
9 namespace mojo {
10 namespace core {
11
WatcherSet(Dispatcher * owner)12 WatcherSet::WatcherSet(Dispatcher* owner) : owner_(owner) {}
13
14 WatcherSet::~WatcherSet() = default;
15
NotifyState(const HandleSignalsState & state)16 void WatcherSet::NotifyState(const HandleSignalsState& state) {
17 // Avoid notifying watchers if they have already seen this state.
18 if (last_known_state_.has_value() && state.equals(last_known_state_.value()))
19 return;
20 last_known_state_ = state;
21 for (const auto& entry : watchers_)
22 entry.first->NotifyHandleState(owner_, state);
23 }
24
NotifyClosed()25 void WatcherSet::NotifyClosed() {
26 for (const auto& entry : watchers_)
27 entry.first->NotifyHandleClosed(owner_);
28 }
29
Add(const scoped_refptr<WatcherDispatcher> & watcher,uintptr_t context,const HandleSignalsState & current_state)30 MojoResult WatcherSet::Add(const scoped_refptr<WatcherDispatcher>& watcher,
31 uintptr_t context,
32 const HandleSignalsState& current_state) {
33 auto it = watchers_.find(watcher.get());
34 if (it == watchers_.end()) {
35 auto result =
36 watchers_.insert(std::make_pair(watcher.get(), Entry{watcher}));
37 it = result.first;
38 }
39
40 if (!it->second.contexts.insert(context).second)
41 return MOJO_RESULT_ALREADY_EXISTS;
42
43 if (last_known_state_.has_value() &&
44 !current_state.equals(last_known_state_.value())) {
45 // This new state may be relevant to everyone, in which case we just
46 // notify everyone.
47 NotifyState(current_state);
48 } else {
49 // Otherwise only notify the newly added Watcher.
50 watcher->NotifyHandleState(owner_, current_state);
51 }
52 return MOJO_RESULT_OK;
53 }
54
Remove(WatcherDispatcher * watcher,uintptr_t context)55 MojoResult WatcherSet::Remove(WatcherDispatcher* watcher, uintptr_t context) {
56 auto it = watchers_.find(watcher);
57 if (it == watchers_.end())
58 return MOJO_RESULT_NOT_FOUND;
59
60 ContextSet& contexts = it->second.contexts;
61 auto context_it = contexts.find(context);
62 if (context_it == contexts.end())
63 return MOJO_RESULT_NOT_FOUND;
64
65 contexts.erase(context_it);
66 if (contexts.empty())
67 watchers_.erase(it);
68
69 return MOJO_RESULT_OK;
70 }
71
Entry(const scoped_refptr<WatcherDispatcher> & dispatcher)72 WatcherSet::Entry::Entry(const scoped_refptr<WatcherDispatcher>& dispatcher)
73 : dispatcher(dispatcher) {}
74
75 WatcherSet::Entry::Entry(Entry&& other) = default;
76
77 WatcherSet::Entry::~Entry() = default;
78
79 WatcherSet::Entry& WatcherSet::Entry::operator=(Entry&& other) = default;
80
81 } // namespace core
82 } // namespace mojo
83