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