diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-11 22:41:48 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-11 22:41:48 +0000 |
commit | ef3797e4d14ce4b64cbbfdcf95843dc9bbdbb5b7 (patch) | |
tree | 243d458b098f7e06fdd00910a406116f5fb2db25 /mojo/system/dispatcher.h | |
parent | 5260b6683833c6d7c014346683b6bfc009f4ae72 (diff) | |
download | chromium_src-ef3797e4d14ce4b64cbbfdcf95843dc9bbdbb5b7.zip chromium_src-ef3797e4d14ce4b64cbbfdcf95843dc9bbdbb5b7.tar.gz chromium_src-ef3797e4d14ce4b64cbbfdcf95843dc9bbdbb5b7.tar.bz2 |
Mojo: Implement plumbing to support passing handles over MessagePipes.
This is tricky for several reasons:
- We have fine-grained locking (and would like to keep it that way),
and need to avoid deadlock. In particular, acquiring multiple
dispatcher locks simultaneously is dangerous -- so we allow it to
fail.
- We want clean failure semantics. In particular, on failure,
WriteMessage() should leave the handles being sent valid. This means
that we may not remove them from the handle table until the call has
succeeded. Thus we have to mark them as busy.
- We need to avoid various races. E.g., still to do: When sending a
handle in-process, it's important that once |WriteMessage()| has
sent a handle, no more calls done on that particular handle may
proceed. As a result, we won't be able to simply transfer
dispatchers to a new handle (in-process) but instead must create a
new dispatcher referencing the same resource. This will also ensure
that |Wait()|s on that handle will be properly cancelled.
R=darin@chromium.org, darin
Review URL: https://codereview.chromium.org/67413003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234302 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/system/dispatcher.h')
-rw-r--r-- | mojo/system/dispatcher.h | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/mojo/system/dispatcher.h b/mojo/system/dispatcher.h index 75f6a97..d1721d6 100644 --- a/mojo/system/dispatcher.h +++ b/mojo/system/dispatcher.h @@ -5,6 +5,8 @@ #ifndef MOJO_SYSTEM_DISPATCHER_H_ #define MOJO_SYSTEM_DISPATCHER_H_ +#include <vector> + #include "base/basictypes.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -14,6 +16,7 @@ namespace mojo { namespace system { +class CoreImpl; class Waiter; // A |Dispatcher| implements Mojo primitives that are "attached" to a particular @@ -32,16 +35,21 @@ class MOJO_SYSTEM_EXPORT Dispatcher : // prevents the various |...ImplNoLock()|s from releasing the lock as soon as // possible. If this becomes an issue, we can rethink this. MojoResult Close(); - MojoResult WriteMessage(const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, + // |dispatchers| may be non-null if and only if there are handles to be + // written, in which case this will be called with all the dispatchers' locks + // held. On success, all the dispatchers must have been moved to a closed + // state; on failure, they should remain in their original state. + MojoResult WriteMessage(const void* bytes, uint32_t num_bytes, + const std::vector<Dispatcher*>* dispatchers, MojoWriteMessageFlags flags); - MojoResult ReadMessage(void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); + // |dispatchers| must be non-null if |max_num_dispatchers| is nonzero. On + // success, it will be set to the dispatchers to be received (and assigned + // handles) as part of the message. + MojoResult ReadMessage( + void* bytes, uint32_t* num_bytes, + uint32_t max_num_dispatchers, + std::vector<scoped_refptr<Dispatcher> >* dispatchers, + MojoReadMessageFlags flags); // Adds a waiter to this dispatcher. The waiter will be woken up when this // object changes state to satisfy |flags| with result |wake_result| (which @@ -74,16 +82,17 @@ class MOJO_SYSTEM_EXPORT Dispatcher : // These are to be overridden by subclasses (if necessary). They are never // called after the dispatcher has been closed. They are called under |lock_|. - virtual MojoResult WriteMessageImplNoLock(const void* bytes, - uint32_t num_bytes, - const MojoHandle* handles, - uint32_t num_handles, - MojoWriteMessageFlags flags); - virtual MojoResult ReadMessageImplNoLock(void* bytes, - uint32_t* num_bytes, - MojoHandle* handles, - uint32_t* num_handles, - MojoReadMessageFlags flags); + // See the descriptions of the methods without the "ImplNoLock" for more + // information. + virtual MojoResult WriteMessageImplNoLock( + const void* bytes, uint32_t num_bytes, + const std::vector<Dispatcher*>* dispatchers, + MojoWriteMessageFlags flags); + virtual MojoResult ReadMessageImplNoLock( + void* bytes, uint32_t* num_bytes, + uint32_t max_num_dispatchers, + std::vector<scoped_refptr<Dispatcher> >* dispatchers, + MojoReadMessageFlags flags); virtual MojoResult AddWaiterImplNoLock(Waiter* waiter, MojoWaitFlags flags, MojoResult wake_result); @@ -94,6 +103,9 @@ class MOJO_SYSTEM_EXPORT Dispatcher : base::Lock& lock() const { return lock_; } private: + // For |WriteMessage()|, |CoreImpl| needs access to |lock()|. + friend class CoreImpl; + // This protects the following members as well as any state added by // subclasses. mutable base::Lock lock_; |