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 |
(...skipping 21 matching lines...) Expand all Loading... |
32 namespace platform { | 32 namespace platform { |
33 class PlatformSharedBufferMapping; | 33 class PlatformSharedBufferMapping; |
34 } | 34 } |
35 | 35 |
36 namespace system { | 36 namespace system { |
37 | 37 |
38 class Awakable; | 38 class Awakable; |
39 class Channel; | 39 class Channel; |
40 class Core; | 40 class Core; |
41 class Dispatcher; | 41 class Dispatcher; |
42 class DispatcherTransport; | |
43 struct Handle; | 42 struct Handle; |
44 class HandleTable; | 43 class HandleTable; |
| 44 class HandleTransport; |
45 class LocalMessagePipeEndpoint; | 45 class LocalMessagePipeEndpoint; |
46 class MessagePipe; | 46 class MessagePipe; |
47 class ProxyMessagePipeEndpoint; | 47 class ProxyMessagePipeEndpoint; |
48 class TransportData; | 48 class TransportData; |
49 | 49 |
50 using DispatcherVector = std::vector<util::RefPtr<Dispatcher>>; | 50 using DispatcherVector = std::vector<util::RefPtr<Dispatcher>>; |
51 | 51 |
52 namespace test { | 52 namespace test { |
53 | 53 |
54 // Test helper. We need to declare it here so we can friend it. | 54 // Test helper. We need to declare it here so we can friend it. |
55 DispatcherTransport HandleTryStartTransport(const Handle& handle); | 55 HandleTransport HandleTryStartTransport(const Handle& handle); |
56 | 56 |
57 } // namespace test | 57 } // namespace test |
58 | 58 |
59 // A |Dispatcher| implements Mojo primitives that are "attached" to a particular | 59 // A |Dispatcher| implements Mojo primitives that are "attached" to a particular |
60 // handle. This includes most (all?) primitives except for |MojoWait...()|. This | 60 // handle. This includes most (all?) primitives except for |MojoWait...()|. This |
61 // object is thread-safe, with its state being protected by a single mutex | 61 // object is thread-safe, with its state being protected by a single mutex |
62 // |mutex_|, which is also made available to implementation subclasses (via the | 62 // |mutex_|, which is also made available to implementation subclasses (via the |
63 // |mutex()| method). | 63 // |mutex()| method). |
64 class Dispatcher : public util::RefCountedThreadSafe<Dispatcher> { | 64 class Dispatcher : public util::RefCountedThreadSafe<Dispatcher> { |
65 public: | 65 public: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 // possible. If this becomes an issue, we can rethink this. | 99 // possible. If this becomes an issue, we can rethink this. |
100 MojoResult Close(); | 100 MojoResult Close(); |
101 | 101 |
102 // |EntrypointClass::MESSAGE_PIPE|: | 102 // |EntrypointClass::MESSAGE_PIPE|: |
103 // |transports| may be non-null if and only if there are handles to be | 103 // |transports| may be non-null if and only if there are handles to be |
104 // written; not that |this| must not be in |transports|. On success, all the | 104 // written; not that |this| must not be in |transports|. On success, all the |
105 // dispatchers in |transports| must have been moved to a closed state; on | 105 // dispatchers in |transports| must have been moved to a closed state; on |
106 // failure, they should remain in their original state. | 106 // failure, they should remain in their original state. |
107 MojoResult WriteMessage(UserPointer<const void> bytes, | 107 MojoResult WriteMessage(UserPointer<const void> bytes, |
108 uint32_t num_bytes, | 108 uint32_t num_bytes, |
109 std::vector<DispatcherTransport>* transports, | 109 std::vector<HandleTransport>* transports, |
110 MojoWriteMessageFlags flags); | 110 MojoWriteMessageFlags flags); |
111 // |dispatchers| must be non-null but empty, if |num_dispatchers| is non-null | 111 // |dispatchers| must be non-null but empty, if |num_dispatchers| is non-null |
112 // and nonzero. On success, it will be set to the dispatchers to be received | 112 // and nonzero. On success, it will be set to the dispatchers to be received |
113 // (and assigned handles) as part of the message. | 113 // (and assigned handles) as part of the message. |
114 MojoResult ReadMessage(UserPointer<void> bytes, | 114 MojoResult ReadMessage(UserPointer<void> bytes, |
115 UserPointer<uint32_t> num_bytes, | 115 UserPointer<uint32_t> num_bytes, |
116 DispatcherVector* dispatchers, | 116 DispatcherVector* dispatchers, |
117 uint32_t* num_dispatchers, | 117 uint32_t* num_dispatchers, |
118 MojoReadMessageFlags flags); | 118 MojoReadMessageFlags flags); |
119 | 119 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 // multiple times for the same |awakable| on the same object, so long as | 188 // multiple times for the same |awakable| on the same object, so long as |
189 // |AddAwakable()| was called at most once.) If |signals_state| is non-null, | 189 // |AddAwakable()| was called at most once.) If |signals_state| is non-null, |
190 // |*signals_state| will be set to the current handle signals state. | 190 // |*signals_state| will be set to the current handle signals state. |
191 void RemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state); | 191 void RemoveAwakable(Awakable* awakable, HandleSignalsState* signals_state); |
192 | 192 |
193 // A dispatcher must be put into a special state in order to be sent across a | 193 // A dispatcher must be put into a special state in order to be sent across a |
194 // message pipe. Outside of tests, only |HandleTableAccess| is allowed to do | 194 // message pipe. Outside of tests, only |HandleTableAccess| is allowed to do |
195 // this, since there are requirements on the handle table (see below). | 195 // this, since there are requirements on the handle table (see below). |
196 // | 196 // |
197 // In this special state, only a restricted set of operations is allowed. | 197 // In this special state, only a restricted set of operations is allowed. |
198 // These are the ones available as |DispatcherTransport| methods. Other | 198 // These are the ones available as |HandleTransport| methods. Other |
199 // |Dispatcher| methods must not be called until |DispatcherTransport::End()| | 199 // |Dispatcher| methods must not be called until |HandleTransport::End()| has |
200 // has been called. | 200 // been called. |
201 class HandleTableAccess { | 201 class HandleTableAccess { |
202 private: | 202 private: |
203 friend class Core; | 203 friend class Core; |
204 friend class HandleTable; | 204 friend class HandleTable; |
205 // Tests also need this, to avoid needing |Core|. | 205 // Tests also need this, to avoid needing |Core|. |
206 friend DispatcherTransport test::HandleTryStartTransport(const Handle&); | 206 friend HandleTransport test::HandleTryStartTransport(const Handle&); |
207 | 207 |
208 // This must be called under the handle table lock and only if the handle | 208 // This must be called under the handle table lock and only if the handle |
209 // table entry is not marked busy. The caller must maintain a reference to | 209 // table entry is not marked busy. The caller must maintain a reference to |
210 // |dispatcher| until |DispatcherTransport::End()| is called. | 210 // |dispatcher| until |HandleTransport::End()| is called. |
211 static DispatcherTransport TryStartTransport(const Handle& handle); | 211 static HandleTransport TryStartTransport(const Handle& handle); |
212 }; | 212 }; |
213 | 213 |
214 // A |TransportData| may serialize dispatchers that are given to it (and which | 214 // A |TransportData| may serialize dispatchers that are given to it (and which |
215 // were previously attached to the |MessageInTransit| that is creating it) to | 215 // were previously attached to the |MessageInTransit| that is creating it) to |
216 // a given |Channel| and then (probably in a different process) deserialize. | 216 // a given |Channel| and then (probably in a different process) deserialize. |
217 // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these | 217 // Note that the |MessageInTransit| "owns" (i.e., has the only ref to) these |
218 // dispatchers, so there are no locking issues. (There's no lock ordering | 218 // dispatchers, so there are no locking issues. (There's no lock ordering |
219 // issue, and in fact no need to take dispatcher locks at all.) | 219 // issue, and in fact no need to take dispatcher locks at all.) |
220 // TODO(vtl): Consider making another wrapper similar to |DispatcherTransport| | 220 // TODO(vtl): Consider making another wrapper similar to |HandleTransport| |
221 // (but with an owning, unique reference), and having | 221 // (but with an owning, unique reference), and having |
222 // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and | 222 // |CreateEquivalentDispatcherAndCloseImplNoLock()| return that wrapper (and |
223 // |MessageInTransit|, etc. only holding on to such wrappers). | 223 // |MessageInTransit|, etc. only holding on to such wrappers). |
224 class TransportDataAccess { | 224 class TransportDataAccess { |
225 private: | 225 private: |
226 friend class TransportData; | 226 friend class TransportData; |
227 | 227 |
228 // Serialization API. These functions may only be called on such | 228 // Serialization API. These functions may only be called on such |
229 // dispatchers. (|channel| is the |Channel| to which the dispatcher is to be | 229 // dispatchers. (|channel| is the |Channel| to which the dispatcher is to be |
230 // serialized.) See the |Dispatcher| methods of the same names for more | 230 // serialized.) See the |Dispatcher| methods of the same names for more |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 virtual util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( | 270 virtual util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock( |
271 MessagePipe* message_pipe, | 271 MessagePipe* message_pipe, |
272 unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0; | 272 unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0; |
273 | 273 |
274 // These are to be overridden by subclasses (if necessary). They are never | 274 // These are to be overridden by subclasses (if necessary). They are never |
275 // called after the dispatcher has been closed. See the descriptions of the | 275 // called after the dispatcher has been closed. See the descriptions of the |
276 // methods without the "ImplNoLock" for more information. | 276 // methods without the "ImplNoLock" for more information. |
277 virtual MojoResult WriteMessageImplNoLock( | 277 virtual MojoResult WriteMessageImplNoLock( |
278 UserPointer<const void> bytes, | 278 UserPointer<const void> bytes, |
279 uint32_t num_bytes, | 279 uint32_t num_bytes, |
280 std::vector<DispatcherTransport>* transports, | 280 std::vector<HandleTransport>* transports, |
281 MojoWriteMessageFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 281 MojoWriteMessageFlags flags) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); |
282 virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, | 282 virtual MojoResult ReadMessageImplNoLock(UserPointer<void> bytes, |
283 UserPointer<uint32_t> num_bytes, | 283 UserPointer<uint32_t> num_bytes, |
284 DispatcherVector* dispatchers, | 284 DispatcherVector* dispatchers, |
285 uint32_t* num_dispatchers, | 285 uint32_t* num_dispatchers, |
286 MojoReadMessageFlags flags) | 286 MojoReadMessageFlags flags) |
287 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 287 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); |
288 virtual MojoResult SetDataPipeProducerOptionsImplNoLock( | 288 virtual MojoResult SetDataPipeProducerOptionsImplNoLock( |
289 UserPointer<const MojoDataPipeProducerOptions> options) | 289 UserPointer<const MojoDataPipeProducerOptions> options) |
290 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 290 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 | 368 |
369 // This should be overridden to return true if/when there's an ongoing | 369 // This should be overridden to return true if/when there's an ongoing |
370 // operation (e.g., two-phase read/writes on data pipes) that should prevent a | 370 // operation (e.g., two-phase read/writes on data pipes) that should prevent a |
371 // handle from being sent over a message pipe (with status "busy"). | 371 // handle from being sent over a message pipe (with status "busy"). |
372 virtual bool IsBusyNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_); | 372 virtual bool IsBusyNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_); |
373 | 373 |
374 util::Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; } | 374 util::Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; } |
375 | 375 |
376 private: | 376 private: |
377 FRIEND_REF_COUNTED_THREAD_SAFE(Dispatcher); | 377 FRIEND_REF_COUNTED_THREAD_SAFE(Dispatcher); |
378 friend class DispatcherTransport; | 378 friend class HandleTransport; |
379 | 379 |
380 // Closes the dispatcher. This must be done under lock, and unlike |Close()|, | 380 // Closes the dispatcher. This must be done under lock, and unlike |Close()|, |
381 // the dispatcher must not be closed already. (This is the "equivalent" of | 381 // the dispatcher must not be closed already. (This is the "equivalent" of |
382 // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the | 382 // |CreateEquivalentDispatcherAndCloseNoLock()|, for situations where the |
383 // dispatcher must be disposed of instead of "transferred".) | 383 // dispatcher must be disposed of instead of "transferred".) |
384 void CloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 384 void CloseNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); |
385 | 385 |
386 // Creates an equivalent dispatcher -- representing the same resource as this | 386 // Creates an equivalent dispatcher -- representing the same resource as this |
387 // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this | 387 // dispatcher -- and close (i.e., disable) this dispatcher. I.e., this |
388 // dispatcher will look as though it was closed, but the resource it | 388 // dispatcher will look as though it was closed, but the resource it |
389 // represents will be assigned to the new dispatcher. This must be called | 389 // represents will be assigned to the new dispatcher. This must be called |
390 // under the dispatcher's lock. If the resulting dispatcher will be put into a | 390 // under the dispatcher's lock. If the resulting dispatcher will be put into a |
391 // message on a message pipe, then |message_pipe| will be set appropriately | 391 // message on a message pipe, then |message_pipe| will be set appropriately |
392 // (otherwise, it may be null) and |port| will be set to the destination port. | 392 // (otherwise, it may be null) and |port| will be set to the destination port. |
393 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock( | 393 util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock( |
394 MessagePipe* message_pipe, | 394 MessagePipe* message_pipe, |
395 unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); | 395 unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_); |
396 | 396 |
397 // API to serialize dispatchers to a |Channel|, exposed to only | 397 // API to serialize dispatchers to a |Channel|, exposed to only |
398 // |TransportData| (via |TransportData|). They may only be called on a | 398 // |TransportData| (via |TransportData|). They may only be called on a |
399 // dispatcher attached to a |MessageInTransit| (and in particular not in | 399 // dispatcher attached to a |MessageInTransit| (and in particular not in |
400 // |CoreImpl|'s handle table). | 400 // |CoreImpl|'s handle table). |
401 // | 401 // |
402 // TODO(vtl): The serialization API (and related implementation methods, | 402 // TODO(vtl): The serialization API (and related implementation methods, |
403 // including |DispatcherTransport|'s methods) is marked | 403 // including |HandleTransport|'s methods) is marked |MOJO_NOT_THREAD_SAFE|. |
404 // |MOJO_NOT_THREAD_SAFE|. This is because the threading requirements are | 404 // This is because the threading requirements are somewhat complicated (e.g., |
405 // somewhat complicated (e.g., |HandleTableAccess::TryStartTransport()| is | 405 // |HandleTableAccess::TryStartTransport()| is really a try-lock function, |
406 // really a try-lock function, amongst other things). We could/should do a | 406 // amongst other things). We could/should do a more careful job annotating |
407 // more careful job annotating these methods. | 407 // these methods. https://github.com/domokit/mojo/issues/322 |
408 // https://github.com/domokit/mojo/issues/322 | |
409 // | 408 // |
410 // Starts the serialization. Returns (via the two "out" parameters) the | 409 // Starts the serialization. Returns (via the two "out" parameters) the |
411 // maximum amount of space that may be needed to serialize this dispatcher to | 410 // maximum amount of space that may be needed to serialize this dispatcher to |
412 // the given |Channel| (no more than | 411 // the given |Channel| (no more than |
413 // |TransportData::kMaxSerializedDispatcherSize|) and the maximum number of | 412 // |TransportData::kMaxSerializedDispatcherSize|) and the maximum number of |
414 // |PlatformHandle|s that may need to be attached (no more than | 413 // |PlatformHandle|s that may need to be attached (no more than |
415 // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this | 414 // |TransportData::kMaxSerializedDispatcherPlatformHandles|). If this |
416 // dispatcher cannot be serialized to the given |Channel|, |*max_size| and | 415 // dispatcher cannot be serialized to the given |Channel|, |*max_size| and |
417 // |*max_platform_handles| should be set to zero. A call to this method will | 416 // |*max_platform_handles| should be set to zero. A call to this method will |
418 // ALWAYS be followed by a call to |EndSerializeAndClose()| (even if this | 417 // ALWAYS be followed by a call to |EndSerializeAndClose()| (even if this |
(...skipping 28 matching lines...) Expand all Loading... |
447 | 446 |
448 // So logging macros and |DCHECK_EQ()|, etc. work. | 447 // So logging macros and |DCHECK_EQ()|, etc. work. |
449 inline std::ostream& operator<<(std::ostream& out, Dispatcher::Type type) { | 448 inline std::ostream& operator<<(std::ostream& out, Dispatcher::Type type) { |
450 return out << static_cast<int>(type); | 449 return out << static_cast<int>(type); |
451 } | 450 } |
452 | 451 |
453 } // namespace system | 452 } // namespace system |
454 } // namespace mojo | 453 } // namespace mojo |
455 | 454 |
456 #endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ | 455 #endif // MOJO_EDK_SYSTEM_DISPATCHER_H_ |
OLD | NEW |