1 // Copyright 2017 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 #ifndef MOJO_CORE_WATCHER_DISPATCHER_H_ 6 #define MOJO_CORE_WATCHER_DISPATCHER_H_ 7 8 #include <stdint.h> 9 10 #include <set> 11 12 #include "base/containers/flat_map.h" 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/synchronization/lock.h" 16 #include "mojo/core/dispatcher.h" 17 #include "mojo/core/handle_signals_state.h" 18 #include "mojo/core/system_impl_export.h" 19 #include "mojo/public/c/system/trap.h" 20 21 namespace mojo { 22 namespace core { 23 24 class Watch; 25 26 // The dispatcher type which backs watcher handles. 27 class WatcherDispatcher : public Dispatcher { 28 public: 29 // Constructs a new WatcherDispatcher which invokes |handler| when a 30 // registered watch observes some relevant state change. 31 explicit WatcherDispatcher(MojoTrapEventHandler handler); 32 33 // Methods used by watched dispatchers to notify watchers of events. 34 void NotifyHandleState(Dispatcher* dispatcher, 35 const HandleSignalsState& state); 36 void NotifyHandleClosed(Dispatcher* dispatcher); 37 38 // Method used by RequestContext (indirectly, via Watch) to complete 39 // notification operations from a safe stack frame to avoid reentrancy. 40 void InvokeWatchCallback(uintptr_t context, 41 MojoResult result, 42 const HandleSignalsState& state, 43 MojoTrapEventFlags flags); 44 45 // Dispatcher: 46 Type GetType() const override; 47 MojoResult Close() override; 48 MojoResult WatchDispatcher(scoped_refptr<Dispatcher> dispatcher, 49 MojoHandleSignals signals, 50 MojoTriggerCondition condition, 51 uintptr_t context) override; 52 MojoResult CancelWatch(uintptr_t context) override; 53 MojoResult Arm(uint32_t* num_blocking_events, 54 MojoTrapEvent* blocking_events) override; 55 56 private: 57 friend class Watch; 58 59 using WatchSet = std::set<const Watch*>; 60 61 ~WatcherDispatcher() override; 62 63 const MojoTrapEventHandler handler_; 64 65 // Guards access to the fields below. 66 // 67 // NOTE: This may be acquired while holding another dispatcher's lock, as 68 // watched dispatchers call into WatcherDispatcher methods which lock this 69 // when issuing state change notifications. WatcherDispatcher must therefore 70 // take caution to NEVER acquire other dispatcher locks while this is held. 71 base::Lock lock_; 72 73 bool armed_ = false; 74 bool closed_ = false; 75 76 // A mapping from context to Watch. 77 base::flat_map<uintptr_t, scoped_refptr<Watch>> watches_; 78 79 // A mapping from watched dispatcher to Watch. 80 base::flat_map<Dispatcher*, scoped_refptr<Watch>> watched_handles_; 81 82 // The set of all Watch instances which are currently ready to signal. This is 83 // used for efficient arming behavior, as it allows for O(1) discovery of 84 // whether or not arming can succeed and quick determination of who's 85 // responsible if it can't. 86 WatchSet ready_watches_; 87 88 // Tracks the last Watch whose state was returned by Arm(). This is used to 89 // ensure consistent round-robin behavior in the event that multiple Watches 90 // remain ready over the span of several Arm() attempts. 91 // 92 // NOTE: This pointer is only used to index |ready_watches_| and may point to 93 // an invalid object. It must therefore never be dereferenced. 94 const Watch* last_watch_to_block_arming_ = nullptr; 95 96 DISALLOW_COPY_AND_ASSIGN(WatcherDispatcher); 97 }; 98 99 } // namespace core 100 } // namespace mojo 101 102 #endif // MOJO_CORE_WATCHER_DISPATCHER_H_ 103