Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: mojo/edk/system/dispatcher.h

Issue 1350023003: Add a Mojo EDK for Chrome that uses one OS pipe per message pipe. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: more cleanup Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698