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