1 // Copyright 2013 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_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_ 6 #define MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_ 7 8 #include <stdint.h> 9 10 #include <functional> 11 #include <memory> 12 #include <set> 13 #include <unordered_map> 14 15 #include "base/macros.h" 16 #include "base/message_loop/message_pump.h" 17 #include "base/observer_list.h" 18 #include "base/synchronization/lock.h" 19 #include "base/synchronization/waitable_event.h" 20 #include "base/time/time.h" 21 #include "mojo/message_pump/mojo_message_pump_export.h" 22 #include "mojo/public/cpp/system/core.h" 23 24 namespace mojo { 25 namespace common { 26 27 class MessagePumpMojoHandler; 28 29 // Mojo implementation of MessagePump. 30 class MOJO_MESSAGE_PUMP_EXPORT MessagePumpMojo : public base::MessagePump { 31 public: 32 class MOJO_MESSAGE_PUMP_EXPORT Observer { 33 public: Observer()34 Observer() {} 35 36 virtual void WillSignalHandler() = 0; 37 virtual void DidSignalHandler() = 0; 38 39 protected: ~Observer()40 virtual ~Observer() {} 41 }; 42 43 MessagePumpMojo(); 44 ~MessagePumpMojo() override; 45 46 // Static factory function (for using with |base::Thread::Options|, wrapped 47 // using |base::Bind()|). 48 static std::unique_ptr<base::MessagePump> Create(); 49 50 // Returns the MessagePumpMojo instance of the current thread, if it exists. 51 static MessagePumpMojo* current(); 52 IsCurrent()53 static bool IsCurrent() { return !!current(); } 54 55 // Registers a MessagePumpMojoHandler for the specified handle. Only one 56 // handler can be registered for a specified handle. 57 // NOTE: a value of 0 for |deadline| indicates an indefinite timeout. 58 void AddHandler(MessagePumpMojoHandler* handler, 59 const Handle& handle, 60 MojoHandleSignals wait_signals, 61 base::TimeTicks deadline); 62 63 void RemoveHandler(const Handle& handle); 64 65 void AddObserver(Observer*); 66 void RemoveObserver(Observer*); 67 68 // MessagePump: 69 void Run(Delegate* delegate) override; 70 void Quit() override; 71 void ScheduleWork() override; 72 void ScheduleDelayedWork(const base::TimeTicks& delayed_work_time) override; 73 74 private: 75 struct RunState; 76 77 // Contains the data needed to track a request to AddHandler(). 78 struct Handler { HandlerHandler79 Handler() : handler(NULL), wait_signals(MOJO_HANDLE_SIGNAL_NONE), id(0) {} 80 81 MessagePumpMojoHandler* handler; 82 MojoHandleSignals wait_signals; 83 base::TimeTicks deadline; 84 // See description of |MessagePumpMojo::next_handler_id_| for details. 85 int id; 86 }; 87 88 struct HandleHasher { operatorHandleHasher89 size_t operator()(const Handle& handle) const { 90 return std::hash<uint32_t>()(static_cast<uint32_t>(handle.value())); 91 } 92 }; 93 94 using HandleToHandler = std::unordered_map<Handle, Handler, HandleHasher>; 95 96 // Implementation of Run(). 97 void DoRunLoop(RunState* run_state, Delegate* delegate); 98 99 // Services the set of handles ready. If |block| is true this waits for a 100 // handle to become ready, otherwise this does not block. Returns |true| if a 101 // handle has become ready, |false| otherwise. 102 bool DoInternalWork(const RunState& run_state, bool block); 103 104 bool DoNonMojoWork(const RunState& run_state, bool block); 105 106 // Waits for handles in the wait set to become ready. Returns |true| if ready 107 // handles may be available, or |false| if the wait's deadline was exceeded. 108 // Note, ready handles may be unavailable, even though |true| was returned. 109 bool WaitForReadyHandles(const RunState& run_state) const; 110 111 // Retrieves any 'ready' handles from the wait set, and runs the handler's 112 // OnHandleReady() or OnHandleError() functions as necessary. Returns |true| 113 // if any handles were ready and processed. 114 bool ProcessReadyHandles(); 115 116 // Removes any handles that have expired their deadline. Runs the handler's 117 // OnHandleError() function with |MOJO_RESULT_DEADLINE_EXCEEDED| as the 118 // result. Returns |true| if any handles were removed. 119 bool RemoveExpiredHandles(); 120 121 void SignalControlPipe(); 122 123 // Returns the deadline for the call to MojoWait(). 124 MojoDeadline GetDeadlineForWait(const RunState& run_state) const; 125 126 // Run |OnHandleReady()| for the handler registered with |handle|. |handle| 127 // must be registered. 128 void SignalHandleReady(Handle handle); 129 130 // Run |OnHandleError()| for the handler registered with |handle| and the 131 // error code |result|. |handle| must be registered, and will be removed 132 // before calling |OnHandleError()|. 133 void SignalHandleError(Handle handle, MojoResult result); 134 135 void WillSignalHandler(); 136 void DidSignalHandler(); 137 138 // If non-NULL we're running (inside Run()). Member is reference to value on 139 // stack. 140 RunState* run_state_; 141 142 // Lock for accessing |run_state_|. In general the only method that we have to 143 // worry about is ScheduleWork(). All other methods are invoked on the same 144 // thread. 145 base::Lock run_state_lock_; 146 147 HandleToHandler handlers_; 148 // Set of handles that have a deadline set. Avoids iterating over all elements 149 // in |handles_| in the common case (no deadline set). 150 // TODO(amistry): Make this better and avoid special-casing deadlines. 151 std::set<Handle> deadline_handles_; 152 153 // An ever increasing value assigned to each Handler::id. Used to detect 154 // uniqueness while notifying. That is, while notifying expired timers we copy 155 // |handlers_| and only notify handlers whose id match. If the id does not 156 // match it means the handler was removed then added so that we shouldn't 157 // notify it. 158 int next_handler_id_; 159 160 base::ObserverList<Observer> observers_; 161 162 // Mojo handle for the wait set. 163 ScopedHandle wait_set_handle_; 164 // Used to wake up run loop from |SignalControlPipe()|. 165 ScopedMessagePipeHandle read_handle_; 166 ScopedMessagePipeHandle write_handle_; 167 168 // Used to sleep until there is more work to do, when the Mojo EDK is shutting 169 // down. 170 base::WaitableEvent event_; 171 172 DISALLOW_COPY_AND_ASSIGN(MessagePumpMojo); 173 }; 174 175 } // namespace common 176 } // namespace mojo 177 178 #endif // MOJO_MESSAGE_PUMP_MESSAGE_PUMP_MOJO_H_ 179