OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef MOJO_EDK_SYSTEM_DISPATCHER_H_ | 5 #ifndef MOJO_EDK_SYSTEM_DISPATCHER_H_ |
6 #define MOJO_EDK_SYSTEM_DISPATCHER_H_ | 6 #define MOJO_EDK_SYSTEM_DISPATCHER_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
11 #include <ostream> | 11 #include <ostream> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "base/memory/ref_counted.h" | 14 #include "base/memory/ref_counted.h" |
15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/synchronization/lock.h" |
16 #include "mojo/edk/embedder/platform_handle_vector.h" | 17 #include "mojo/edk/embedder/platform_handle_vector.h" |
17 #include "mojo/edk/system/handle_signals_state.h" | 18 #include "mojo/edk/system/handle_signals_state.h" |
18 #include "mojo/edk/system/memory.h" | 19 #include "mojo/edk/system/memory.h" |
19 #include "mojo/edk/system/mutex.h" | |
20 #include "mojo/edk/system/system_impl_export.h" | 20 #include "mojo/edk/system/system_impl_export.h" |
21 #include "mojo/public/c/system/buffer.h" | 21 #include "mojo/public/c/system/buffer.h" |
22 #include "mojo/public/c/system/data_pipe.h" | 22 #include "mojo/public/c/system/data_pipe.h" |
23 #include "mojo/public/c/system/message_pipe.h" | 23 #include "mojo/public/c/system/message_pipe.h" |
24 #include "mojo/public/c/system/types.h" | 24 #include "mojo/public/c/system/types.h" |
25 #include "mojo/public/cpp/system/macros.h" | 25 #include "mojo/public/cpp/system/macros.h" |
26 | 26 |
27 namespace mojo { | 27 namespace mojo { |
| 28 namespace edk { |
28 | 29 |
29 namespace embedder { | |
30 class PlatformSharedBufferMapping; | |
31 } | |
32 | |
33 namespace system { | |
34 | |
35 class Channel; | |
36 class Core; | 30 class Core; |
37 class Dispatcher; | 31 class Dispatcher; |
38 class DispatcherTransport; | 32 class DispatcherTransport; |
39 class HandleTable; | 33 class HandleTable; |
40 class LocalMessagePipeEndpoint; | 34 class LocalMessagePipeEndpoint; |
| 35 class PlatformSharedBufferMapping; |
41 class ProxyMessagePipeEndpoint; | 36 class ProxyMessagePipeEndpoint; |
42 class TransportData; | 37 class TransportData; |
43 class Awakable; | 38 class Awakable; |
44 | 39 |
45 using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; | 40 using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>; |
46 | 41 |
47 namespace test { | 42 namespace test { |
48 | 43 |
49 // Test helper. We need to declare it here so we can friend it. | 44 // Test helper. We need to declare it here so we can friend it. |
50 MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport | 45 MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport |
51 DispatcherTryStartTransport(Dispatcher* dispatcher); | 46 DispatcherTryStartTransport(Dispatcher* dispatcher); |
52 | 47 |
53 } // namespace test | 48 } // namespace test |
54 | 49 |
55 // A |Dispatcher| implements Mojo primitives that are "attached" to a particular | 50 // A |Dispatcher| implements Mojo primitives that are "attached" to a particular |
56 // handle. This includes most (all?) primitives except for |MojoWait...()|. This | 51 // handle. This includes most (all?) primitives except for |MojoWait...()|. This |
57 // object is thread-safe, with its state being protected by a single mutex | 52 // object is thread-safe, with its state being protected by a single lock |
58 // |mutex_|, which is also made available to implementation subclasses (via the | 53 // |lock_|, which is also made available to implementation subclasses (via the |
59 // |mutex()| method). | 54 // |lock()| method). |
60 class MOJO_SYSTEM_IMPL_EXPORT Dispatcher | 55 class MOJO_SYSTEM_IMPL_EXPORT Dispatcher |
61 : public base::RefCountedThreadSafe<Dispatcher> { | 56 : public base::RefCountedThreadSafe<Dispatcher> { |
62 public: | 57 public: |
63 enum class Type { | 58 enum class Type { |
64 UNKNOWN = 0, | 59 UNKNOWN = 0, |
65 MESSAGE_PIPE, | 60 MESSAGE_PIPE, |
66 DATA_PIPE_PRODUCER, | 61 DATA_PIPE_PRODUCER, |
67 DATA_PIPE_CONSUMER, | 62 DATA_PIPE_CONSUMER, |
68 SHARED_BUFFER, | 63 SHARED_BUFFER, |
69 | 64 |
70 // "Private" types (not exposed via the public interface): | 65 // "Private" types (not exposed via the public interface): |
71 PLATFORM_HANDLE = -1 | 66 PLATFORM_HANDLE = -1 |
72 }; | 67 }; |
73 virtual Type GetType() const = 0; | 68 virtual Type GetType() const = 0; |
74 | 69 |
75 // These methods implement the various primitives named |Mojo...()|. These | 70 // These methods implement the various primitives named |Mojo...()|. These |
76 // take |mutex_| and handle races with |Close()|. Then they call out to | 71 // take |lock_| and handle races with |Close()|. Then they call out to |
77 // subclasses' |...ImplNoLock()| methods (still under |mutex_|), which | 72 // subclasses' |...ImplNoLock()| methods (still under |lock_|), which actually |
78 // actually implement the primitives. | 73 // implement the primitives. |
79 // NOTE(vtl): This puts a big lock around each dispatcher (i.e., handle), and | 74 // NOTE(vtl): This puts a big lock around each dispatcher (i.e., handle), and |
80 // prevents the various |...ImplNoLock()|s from releasing the lock as soon as | 75 // prevents the various |...ImplNoLock()|s from releasing the lock as soon as |
81 // possible. If this becomes an issue, we can rethink this. | 76 // possible. If this becomes an issue, we can rethink this. |
82 MojoResult Close(); | 77 MojoResult Close(); |
83 | 78 |
84 // |transports| may be non-null if and only if there are handles to be | 79 // |transports| may be non-null if and only if there are handles to be |
85 // written; not that |this| must not be in |transports|. On success, all the | 80 // written; not that |this| must not be in |transports|. On success, all the |
86 // dispatchers in |transports| must have been moved to a closed state; on | 81 // dispatchers in |transports| must have been moved to a closed state; on |
87 // failure, they should remain in their original state. | 82 // failure, they should remain in their original state. |
88 MojoResult WriteMessage(UserPointer<const void> bytes, | 83 MojoResult WriteMessage(UserPointer<const void> bytes, |
(...skipping 25 matching lines...) Expand all Loading... |
114 // |options| may be null. |new_dispatcher| must not be null, but | 109 // |options| may be null. |new_dispatcher| must not be null, but |
115 // |*new_dispatcher| should be null (and will contain the dispatcher for the | 110 // |*new_dispatcher| should be null (and will contain the dispatcher for the |
116 // new handle on success). | 111 // new handle on success). |
117 MojoResult DuplicateBufferHandle( | 112 MojoResult DuplicateBufferHandle( |
118 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 113 UserPointer<const MojoDuplicateBufferHandleOptions> options, |
119 scoped_refptr<Dispatcher>* new_dispatcher); | 114 scoped_refptr<Dispatcher>* new_dispatcher); |
120 MojoResult MapBuffer( | 115 MojoResult MapBuffer( |
121 uint64_t offset, | 116 uint64_t offset, |
122 uint64_t num_bytes, | 117 uint64_t num_bytes, |
123 MojoMapBufferFlags flags, | 118 MojoMapBufferFlags flags, |
124 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping); | 119 scoped_ptr<PlatformSharedBufferMapping>* mapping); |
125 | 120 |
126 // Gets the current handle signals state. (The default implementation simply | 121 // Gets the current handle signals state. (The default implementation simply |
127 // returns a default-constructed |HandleSignalsState|, i.e., no signals | 122 // returns a default-constructed |HandleSignalsState|, i.e., no signals |
128 // satisfied or satisfiable.) Note: The state is subject to change from other | 123 // satisfied or satisfiable.) Note: The state is subject to change from other |
129 // threads. | 124 // threads. |
130 HandleSignalsState GetHandleSignalsState() const; | 125 HandleSignalsState GetHandleSignalsState() const; |
131 | 126 |
132 // Adds an awakable to this dispatcher, which will be woken up when this | 127 // Adds an awakable to this dispatcher, which will be woken up when this |
133 // object changes state to satisfy |signals| with context |context|. It will | 128 // object changes state to satisfy |signals| with context |context|. It will |
134 // also be woken up when it becomes impossible for the object to ever satisfy | 129 // also be woken up when it becomes impossible for the object to ever satisfy |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 // Tests also need this, to avoid needing |Core|. | 163 // Tests also need this, to avoid needing |Core|. |
169 friend DispatcherTransport test::DispatcherTryStartTransport(Dispatcher*); | 164 friend DispatcherTransport test::DispatcherTryStartTransport(Dispatcher*); |
170 | 165 |
171 // This must be called under the handle table lock and only if the handle | 166 // This must be called under the handle table lock and only if the handle |
172 // table entry is not marked busy. The caller must maintain a reference to | 167 // table entry is not marked busy. The caller must maintain a reference to |
173 // |dispatcher| until |DispatcherTransport::End()| is called. | 168 // |dispatcher| until |DispatcherTransport::End()| is called. |
174 static DispatcherTransport TryStartTransport(Dispatcher* dispatcher); | 169 static DispatcherTransport TryStartTransport(Dispatcher* dispatcher); |
175 }; | 170 }; |
176 | 171 |
177 // A |TransportData| may serialize dispatchers that are given to it (and which | 172 // A |TransportData| may serialize dispatchers that are given to it (and which |
178 // were previously attached to the |MessageInTransit| that is creating it) to | 173 // were previously attached to the |MessageInTransit| that is creating it) and |
179 // a given |Channel| and then (probably in a different process) deserialize. | 174 // and then (probably in a different process) deserialize. |
180 // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these | 175 // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these |
181 // dispatchers, so there are no locking issues. (There's no lock ordering | 176 // dispatchers, so there are no locking issues. (There's no lock ordering |
182 // issue, and in fact no need to take dispatcher locks at all.) | 177 // issue, and in fact no need to take dispatcher locks at all.) |
183 // TODO(vtl): Consider making another wrapper similar to |DispatcherTransport| | 178 // TODO(vtl): Consider making another wrapper similar to |DispatcherTransport| |
184 // (but with an owning, unique reference), and having | 179 // (but with an owning, unique reference), and having |
185 // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and | 180 // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and |
186 // |MessageInTransit|, etc. only holding on to such wrappers). | 181 // |MessageInTransit|, etc. only holding on to such wrappers). |
187 class TransportDataAccess { | 182 class TransportDataAccess { |
188 private: | 183 private: |
189 friend class TransportData; | 184 friend class TransportData; |
190 | 185 |
191 // Serialization API. These functions may only be called on such | 186 // Serialization API. These functions may only be called on such |
192 // dispatchers. (|channel| is the |Channel| to which the dispatcher is to be | 187 // dispatchers. See the |Dispatcher| methods of the same names for more |
193 // serialized.) See the |Dispatcher| methods of the same names for more | |
194 // details. | 188 // details. |
195 static void StartSerialize(Dispatcher* dispatcher, | 189 static void StartSerialize(Dispatcher* dispatcher, |
196 Channel* channel, | |
197 size_t* max_size, | 190 size_t* max_size, |
198 size_t* max_platform_handles); | 191 size_t* max_platform_handles); |
199 static bool EndSerializeAndClose( | 192 static bool EndSerializeAndClose( |
200 Dispatcher* dispatcher, | 193 Dispatcher* dispatcher, |
201 Channel* channel, | |
202 void* destination, | 194 void* destination, |
203 size_t* actual_size, | 195 size_t* actual_size, |
204 embedder::PlatformHandleVector* platform_handles); | 196 PlatformHandleVector* platform_handles); |
205 | 197 |
206 // Deserialization API. | 198 // Deserialization API. |
207 // Note: This "clears" (i.e., reset to the invalid handle) any platform | 199 // Note: This "clears" (i.e., reset to the invalid handle) any platform |
208 // handles that it takes ownership of. | 200 // handles that it takes ownership of. |
209 static scoped_refptr<Dispatcher> Deserialize( | 201 static scoped_refptr<Dispatcher> Deserialize( |
210 Channel* channel, | |
211 int32_t type, | 202 int32_t type, |
212 const void* source, | 203 const void* source, |
213 size_t size, | 204 size_t size, |
214 embedder::PlatformHandleVector* platform_handles); | 205 PlatformHandleVector* platform_handles); |
215 }; | 206 }; |
216 | 207 |
217 protected: | 208 protected: |
218 friend class base::RefCountedThreadSafe<Dispatcher>; | 209 friend class base::RefCountedThreadSafe<Dispatcher>; |
| 210 friend class MessagePipeDispatcher; // For TransportStarted/TransportEnded. |
219 | 211 |
220 Dispatcher(); | 212 Dispatcher(); |
221 virtual ~Dispatcher(); | 213 virtual ~Dispatcher(); |
222 | 214 |
223 // These are to be overridden by subclasses (if necessary). They are called | 215 // These are to be overridden by subclasses (if necessary). They are called |
224 // exactly once (first |CancelAllAwakablesNoLock()|, then |CloseImplNoLock()|) | 216 // exactly once -- first |CancelAllAwakablesNoLock()|, then |
225 // when the dispatcher is being closed. | 217 // |CloseImplNoLock()|, |
226 virtual void CancelAllAwakablesNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 218 // when the dispatcher is being closed. They are called under |lock_|. |
227 virtual void CloseImplNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 219 virtual void CancelAllAwakablesNoLock(); |
228 | 220 virtual void CloseImplNoLock(); |
229 virtual scoped_refptr<Dispatcher> | 221 virtual scoped_refptr<Dispatcher> |
230 CreateEquivalentDispatcherAndCloseImplNoLock() | 222 CreateEquivalentDispatcherAndCloseImplNoLock() = 0; |
231 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0; | |
232 | 223 |
233 // These are to be overridden by subclasses (if necessary). They are never | 224 // These are to be overridden by subclasses (if necessary). They are never |
234 // called after the dispatcher has been closed. See the descriptions of the | 225 // called after the dispatcher has been closed. They are called under |lock_|. |
235 // methods without the "ImplNoLock" for more information. | 226 // See the descriptions of the methods without the "ImplNoLock" for more |
| 227 // information. |
236 virtual MojoResult WriteMessageImplNoLock( | 228 virtual MojoResult WriteMessageImplNoLock( |
237 UserPointer<const void> bytes, | 229 UserPointer<const void> bytes, |
238 uint32_t num_bytes, | 230 uint32_t num_bytes, |
239 std::vector<DispatcherTransport>* transports, | 231 std::vector<DispatcherTransport>* transports, |
240 MojoWriteMessageFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 232 MojoWriteMessageFlags flags); |
241 virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, | 233 virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, |
242 UserPointer<uint32_t> num_bytes, | 234 UserPointer<uint32_t> num_bytes, |
243 DispatcherVector* dispatchers, | 235 DispatcherVector* dispatchers, |
244 uint32_t* num_dispatchers, | 236 uint32_t* num_dispatchers, |
245 MojoReadMessageFlags flags) | 237 MojoReadMessageFlags flags); |
246 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
247 virtual MojoResult WriteDataImplNoLock(UserPointer<const void> elements, | 238 virtual MojoResult WriteDataImplNoLock(UserPointer<const void> elements, |
248 UserPointer<uint32_t> num_bytes, | 239 UserPointer<uint32_t> num_bytes, |
249 MojoWriteDataFlags flags) | 240 MojoWriteDataFlags flags); |
250 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
251 virtual MojoResult BeginWriteDataImplNoLock( | 241 virtual MojoResult BeginWriteDataImplNoLock( |
252 UserPointer<void*> buffer, | 242 UserPointer<void*> buffer, |
253 UserPointer<uint32_t> buffer_num_bytes, | 243 UserPointer<uint32_t> buffer_num_bytes, |
254 MojoWriteDataFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 244 MojoWriteDataFlags flags); |
255 virtual MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written) | 245 virtual MojoResult EndWriteDataImplNoLock(uint32_t num_bytes_written); |
256 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
257 virtual MojoResult ReadDataImplNoLock(UserPointer<void> elements, | 246 virtual MojoResult ReadDataImplNoLock(UserPointer<void> elements, |
258 UserPointer<uint32_t> num_bytes, | 247 UserPointer<uint32_t> num_bytes, |
259 MojoReadDataFlags flags) | 248 MojoReadDataFlags flags); |
260 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
261 virtual MojoResult BeginReadDataImplNoLock( | 249 virtual MojoResult BeginReadDataImplNoLock( |
262 UserPointer<const void*> buffer, | 250 UserPointer<const void*> buffer, |
263 UserPointer<uint32_t> buffer_num_bytes, | 251 UserPointer<uint32_t> buffer_num_bytes, |
264 MojoReadDataFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 252 MojoReadDataFlags flags); |
265 virtual MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read) | 253 virtual MojoResult EndReadDataImplNoLock(uint32_t num_bytes_read); |
266 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
267 virtual MojoResult DuplicateBufferHandleImplNoLock( | 254 virtual MojoResult DuplicateBufferHandleImplNoLock( |
268 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 255 UserPointer<const MojoDuplicateBufferHandleOptions> options, |
269 scoped_refptr<Dispatcher>* new_dispatcher) | 256 scoped_refptr<Dispatcher>* new_dispatcher); |
270 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
271 virtual MojoResult MapBufferImplNoLock( | 257 virtual MojoResult MapBufferImplNoLock( |
272 uint64_t offset, | 258 uint64_t offset, |
273 uint64_t num_bytes, | 259 uint64_t num_bytes, |
274 MojoMapBufferFlags flags, | 260 MojoMapBufferFlags flags, |
275 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) | 261 scoped_ptr<PlatformSharedBufferMapping>* mapping); |
276 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 262 virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const; |
277 virtual HandleSignalsState GetHandleSignalsStateImplNoLock() const | |
278 MOJO_SHARED_LOCKS_REQUIRED(mutex_); | |
279 virtual MojoResult AddAwakableImplNoLock(Awakable* awakable, | 263 virtual MojoResult AddAwakableImplNoLock(Awakable* awakable, |
280 MojoHandleSignals signals, | 264 MojoHandleSignals signals, |
281 uint32_t context, | 265 uint32_t context, |
282 HandleSignalsState* signals_state) | 266 HandleSignalsState* signals_state); |
283 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
284 virtual void RemoveAwakableImplNoLock(Awakable* awakable, | 267 virtual void RemoveAwakableImplNoLock(Awakable* awakable, |
285 HandleSignalsState* signals_state) | 268 HandleSignalsState* signals_state); |
286 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
287 | 269 |
288 // These implement the API used to serialize dispatchers to a |Channel| | 270 // These implement the API used to serialize dispatchers (described below). |
289 // (described below). They will only be called on a dispatcher that's attached | 271 // They will only be called on a dispatcher that's attached to and "owned" by |
290 // to and "owned" by a |MessageInTransit|. See the non-"impl" versions for | 272 // a |MessageInTransit|. See the non-"impl" versions for more information. |
291 // more information. | |
292 // | 273 // |
293 // Note: |StartSerializeImplNoLock()| is actually called with |mutex_| NOT | 274 // Note: |StartSerializeImplNoLock()| is actually called with |lock_| NOT |
294 // held, since the dispatcher should only be accessible to the calling thread. | 275 // held, since the dispatcher should only be accessible to the calling thread. |
295 // On Debug builds, |EndSerializeAndCloseImplNoLock()| is called with |mutex_| | 276 // On Debug builds, |EndSerializeAndCloseImplNoLock()| is called with |lock_| |
296 // held, to satisfy any |mutex_.AssertHeld()| (e.g., in |CloseImplNoLock()| -- | 277 // held, to satisfy any |lock_.AssertAcquired()| (e.g., in |CloseImplNoLock()| |
297 // and anything it calls); disentangling those assertions is | 278 // -- and anything it calls); disentangling those assertions is |
298 // difficult/fragile, and would weaken our general checking of invariants. | 279 // difficult/fragile, and would weaken our general checking of invariants. |
299 // | 280 // |
300 // TODO(vtl): Consider making these pure virtual once most things support | 281 // TODO(vtl): Consider making these pure virtual once most things support |
301 // being passed over a message pipe. | 282 // being passed over a message pipe. |
302 virtual void StartSerializeImplNoLock(Channel* channel, | 283 virtual void StartSerializeImplNoLock(size_t* max_size, |
303 size_t* max_size, | 284 size_t* max_platform_handles); |
304 size_t* max_platform_handles) | |
305 MOJO_NOT_THREAD_SAFE; | |
306 virtual bool EndSerializeAndCloseImplNoLock( | 285 virtual bool EndSerializeAndCloseImplNoLock( |
307 Channel* channel, | |
308 void* destination, | 286 void* destination, |
309 size_t* actual_size, | 287 size_t* actual_size, |
310 embedder::PlatformHandleVector* platform_handles) MOJO_NOT_THREAD_SAFE; | 288 PlatformHandleVector* platform_handles); |
| 289 |
| 290 // These are called before and after a dispatcher is being transported. i.e. |
| 291 // |TransportStarted| is called |StartSerializeImplNoLock| and |
| 292 // |TransportEnded| is called after |EndSerializeAndCloseImplNoLock|. They are |
| 293 // needed to avoid deadlocks when transporting a dispatcher. The reason is |
| 294 // that |StartSerializeImplNoLock| is called on the main thread and will lead |
| 295 // to calling RawChannel::ReleaseHandle. The dispatcher is locked and it will |
| 296 // acquire RawChannel's locks as well. however the RawChannel could have its |
| 297 // locks acquired on the IO thread and be waiting to acquire the dispatcher's |
| 298 // lock. To solve this deadlock, |TransportStarted| is called before the |
| 299 // dispatcher's lock is acquired. |
| 300 virtual void TransportStarted() {} |
| 301 virtual void TransportEnded() {} |
311 | 302 |
312 // This should be overridden to return true if/when there's an ongoing | 303 // This should be overridden to return true if/when there's an ongoing |
313 // operation (e.g., two-phase read/writes on data pipes) that should prevent a | 304 // operation (e.g., two-phase read/writes on data pipes) that should prevent a |
314 // handle from being sent over a message pipe (with status "busy"). | 305 // handle from being sent over a message pipe (with status "busy"). |
315 virtual bool IsBusyNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_); | 306 virtual bool IsBusyNoLock() const; |
316 | 307 |
317 Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; } | 308 // Available to subclasses. (Note: Returns a non-const reference, just like |
| 309 // |base::AutoLock|'s constructor takes a non-const reference.) |
| 310 base::Lock& lock() const { return lock_; } |
318 | 311 |
319 private: | 312 private: |
320 friend class DispatcherTransport; | 313 friend class DispatcherTransport; |
321 | 314 |
322 // Closes the dispatcher. This must be done under lock, and unlike |Close()|, | 315 // Closes the dispatcher. This must be done under lock, and unlike |Close()|, |
323 // the dispatcher must not be closed already. (This is the "equivalent" of | 316 // the dispatcher must not be closed already. (This is the "equivalent" of |
324 // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the | 317 // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the |
325 // dispatcher must be disposed of instead of "transferred".) | 318 // dispatcher must be disposed of instead of "transferred".) |
326 void CloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 319 void CloseNoLock(); |
327 | 320 |
328 // Creates an equivalent dispatcher -- representing the same resource as this | 321 // Creates an equivalent dispatcher -- representing the same resource as this |
329 // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this | 322 // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this |
330 // dispatcher will look as though it was closed, but the resource it | 323 // dispatcher will look as though it was closed, but the resource it |
331 // represents will be assigned to the new dispatcher. This must be called | 324 // represents will be assigned to the new dispatcher. This must be called |
332 // under the dispatcher's lock. | 325 // under the dispatcher's lock. |
333 scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock() | 326 scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock(); |
334 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | |
335 | 327 |
336 // API to serialize dispatchers to a |Channel|, exposed to only | 328 // API to serialize dispatchers, exposed to only |TransportData| (via |
337 // |TransportData| (via |TransportData|). They may only be called on a | 329 // |TransportData|). They may only be called on a dispatcher attached to a |
338 // dispatcher attached to a |MessageInTransit| (and in particular not in | 330 // |MessageInTransit| (and in particular not in |CoreImpl|'s handle table). |
339 // |CoreImpl|'s handle table). | |
340 // | |
341 // TODO(vtl): The serialization API (and related implementation methods, | |
342 // including |DispatcherTransport|'s methods) is marked | |
343 // |MOJO_NOT_THREAD_SAFE|. This is because the threading requirements are | |
344 // somewhat complicated (e.g., |HandleTableAccess::TryStartTransport()| is | |
345 // really a try-lock function, amongst other things). We could/should do a | |
346 // more careful job annotating these methods. | |
347 // https://github.com/domokit/mojo/issues/322 | |
348 // | 331 // |
349 // Starts the serialization. Returns (via the two "out" parameters) the | 332 // Starts the serialization. Returns (via the two "out" parameters) the |
350 // maximum amount of space that may be needed to serialize this dispatcher to | 333 // maximum amount of space that may be needed to serialize this dispatcher (no |
351 // the given |Channel| (no more than | 334 // more than |TransportData::kMaxSerializedDispatcherSize|) and the maximum |
352 // |TransportData::kMaxSerializedDispatcherSize|) and the maximum number of | 335 // number of |PlatformHandle|s that may need to be attached (no more than |
353 // |PlatformHandle|s that may need to be attached (no more than | |
354 // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this | 336 // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this |
355 // dispatcher cannot be serialized to the given |Channel|, |*max_size| and | 337 // dispatcher cannot be serialized, |*max_size| and |*max_platform_handles| |
356 // |*max_platform_handles| should be set to zero. A call to this method will | 338 // should be set to zero. A call to this method will ALWAYS be followed by a |
357 // ALWAYS be followed by a call to |EndSerializeAndClose()| (even if this | 339 // call to |EndSerializeAndClose()| (even if this dispatcher cannot be |
358 // dispatcher cannot be serialized to the given |Channel|). | 340 // serialized). |
359 void StartSerialize(Channel* channel, | 341 void StartSerialize(size_t* max_size, |
360 size_t* max_size, | 342 size_t* max_platform_handles); |
361 size_t* max_platform_handles) MOJO_NOT_THREAD_SAFE; | 343 // Completes the serialization of this dispatcher and closes it. (This call |
362 // Completes the serialization of this dispatcher to the given |Channel| and | 344 // will always follow an earlier call to |StartSerialize()|. This does so by |
363 // closes it. (This call will always follow an earlier call to | 345 // writing to |destination| and appending any |PlatformHandle|s needed to |
364 // |StartSerialize()|, with the same |Channel|.) This does so by writing to | |
365 // |destination| and appending any |PlatformHandle|s needed to | |
366 // |platform_handles| (which may be null if no platform handles were indicated | 346 // |platform_handles| (which may be null if no platform handles were indicated |
367 // to be required to |StartSerialize()|). This may write no more than the | 347 // to be required to |StartSerialize()|). This may write no more than the |
368 // amount indicated by |StartSerialize()|. (WARNING: Beware of races, e.g., if | 348 // amount indicated by |StartSerialize()|. (WARNING: Beware of races, e.g., if |
369 // something can be mutated between the two calls!) Returns true on success, | 349 // something can be mutated between the two calls!) Returns true on success, |
370 // in which case |*actual_size| is set to the amount it actually wrote to | 350 // in which case |*actual_size| is set to the amount it actually wrote to |
371 // |destination|. On failure, |*actual_size| should not be modified; however, | 351 // |destination|. On failure, |*actual_size| should not be modified; however, |
372 // the dispatcher will still be closed. | 352 // the dispatcher will still be closed. |
373 bool EndSerializeAndClose(Channel* channel, | 353 bool EndSerializeAndClose(void* destination, |
374 void* destination, | |
375 size_t* actual_size, | 354 size_t* actual_size, |
376 embedder::PlatformHandleVector* platform_handles) | 355 PlatformHandleVector* platform_handles); |
377 MOJO_NOT_THREAD_SAFE; | |
378 | 356 |
379 // This protects the following members as well as any state added by | 357 // This protects the following members as well as any state added by |
380 // subclasses. | 358 // subclasses. |
381 mutable Mutex mutex_; | 359 mutable base::Lock lock_; |
382 bool is_closed_ MOJO_GUARDED_BY(mutex_); | 360 bool is_closed_; |
383 | 361 |
384 MOJO_DISALLOW_COPY_AND_ASSIGN(Dispatcher); | 362 MOJO_DISALLOW_COPY_AND_ASSIGN(Dispatcher); |
385 }; | 363 }; |
386 | 364 |
387 // Wrapper around a |Dispatcher| pointer, while it's being processed to be | 365 // Wrapper around a |Dispatcher| pointer, while it's being processed to be |
388 // passed in a message pipe. See the comment about | 366 // passed in a message pipe. See the comment about |
389 // |Dispatcher::HandleTableAccess| for more details. | 367 // |Dispatcher::HandleTableAccess| for more details. |
390 // | 368 // |
391 // Note: This class is deliberately "thin" -- no more expensive than a | 369 // Note: This class is deliberately "thin" -- no more expensive than a |
392 // |Dispatcher*|. | 370 // |Dispatcher*|. |
393 class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { | 371 class MOJO_SYSTEM_IMPL_EXPORT DispatcherTransport { |
394 public: | 372 public: |
395 DispatcherTransport() : dispatcher_(nullptr) {} | 373 DispatcherTransport() : dispatcher_(nullptr) {} |
396 | 374 |
397 void End() MOJO_NOT_THREAD_SAFE; | 375 void End(); |
398 | 376 |
399 Dispatcher::Type GetType() const { return dispatcher_->GetType(); } | 377 Dispatcher::Type GetType() const { return dispatcher_->GetType(); } |
400 bool IsBusy() const MOJO_NOT_THREAD_SAFE { | 378 bool IsBusy() const { return dispatcher_->IsBusyNoLock(); } |
401 return dispatcher_->IsBusyNoLock(); | 379 void Close() { dispatcher_->CloseNoLock(); } |
402 } | 380 scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndClose() { |
403 void Close() MOJO_NOT_THREAD_SAFE { dispatcher_->CloseNoLock(); } | |
404 scoped_refptr<Dispatcher> CreateEquivalentDispatcherAndClose() | |
405 MOJO_NOT_THREAD_SAFE { | |
406 return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock(); | 381 return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock(); |
407 } | 382 } |
408 | 383 |
409 bool is_valid() const { return !!dispatcher_; } | 384 bool is_valid() const { return !!dispatcher_; } |
410 | 385 |
411 protected: | 386 protected: |
412 Dispatcher* dispatcher() { return dispatcher_; } | 387 Dispatcher* dispatcher() { return dispatcher_; } |
413 | 388 |
414 private: | 389 private: |
415 friend class Dispatcher::HandleTableAccess; | 390 friend class Dispatcher::HandleTableAccess; |
| 391 friend class MessagePipeDispatcher; // For AttachTransportsNoLock. |
416 | 392 |
417 explicit DispatcherTransport(Dispatcher* dispatcher) | 393 explicit DispatcherTransport(Dispatcher* dispatcher) |
418 : dispatcher_(dispatcher) {} | 394 : dispatcher_(dispatcher) {} |
419 | 395 |
420 Dispatcher* dispatcher_; | 396 Dispatcher* dispatcher_; |
421 | 397 |
422 // Copy and assign allowed. | 398 // Copy and assign allowed. |
423 }; | 399 }; |
424 | 400 |
425 // So logging macros and |DCHECK_EQ()|, etc. work. | 401 // So logging macros and |DCHECK_EQ()|, etc. work. |
426 MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, | 402 MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out, |
427 Dispatcher::Type type) { | 403 Dispatcher::Type type) { |
428 return out << static_cast<int>(type); | 404 return out << static_cast<int>(type); |
429 } | 405 } |
430 | 406 |
431 } // namespace system | 407 } // namespace edk |
432 } // namespace mojo | 408 } // namespace mojo |
433 | 409 |
434 #endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ | 410 #endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ |
OLD | NEW |