| 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 |