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