Home | History | Annotate | Download | only in system
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef MOJO_EDK_SYSTEM_DISPATCHER_H_
      6 #define MOJO_EDK_SYSTEM_DISPATCHER_H_
      7 
      8 #include <stddef.h>
      9 #include <stdint.h>
     10 
     11 #include <memory>
     12 #include <ostream>
     13 #include <vector>
     14 
     15 #include "base/macros.h"
     16 #include "base/memory/ref_counted.h"
     17 #include "base/synchronization/lock.h"
     18 #include "mojo/edk/embedder/platform_handle.h"
     19 #include "mojo/edk/embedder/platform_shared_buffer.h"
     20 #include "mojo/edk/system/handle_signals_state.h"
     21 #include "mojo/edk/system/ports/name.h"
     22 #include "mojo/edk/system/system_impl_export.h"
     23 #include "mojo/edk/system/watcher.h"
     24 #include "mojo/public/c/system/buffer.h"
     25 #include "mojo/public/c/system/data_pipe.h"
     26 #include "mojo/public/c/system/message_pipe.h"
     27 #include "mojo/public/c/system/types.h"
     28 
     29 namespace mojo {
     30 namespace edk {
     31 
     32 class Awakable;
     33 class Dispatcher;
     34 class MessageForTransit;
     35 
     36 using DispatcherVector = std::vector<scoped_refptr<Dispatcher>>;
     37 
     38 // A |Dispatcher| implements Mojo EDK calls that are associated with a
     39 // particular MojoHandle, with the exception of MojoWait and MojoWaitMany (
     40 // which are implemented directly in Core.).
     41 class MOJO_SYSTEM_IMPL_EXPORT Dispatcher
     42     : public base::RefCountedThreadSafe<Dispatcher> {
     43  public:
     44   struct DispatcherInTransit {
     45     DispatcherInTransit();
     46     DispatcherInTransit(const DispatcherInTransit& other);
     47     ~DispatcherInTransit();
     48 
     49     scoped_refptr<Dispatcher> dispatcher;
     50     MojoHandle local_handle;
     51   };
     52 
     53   enum class Type {
     54     UNKNOWN = 0,
     55     MESSAGE_PIPE,
     56     DATA_PIPE_PRODUCER,
     57     DATA_PIPE_CONSUMER,
     58     SHARED_BUFFER,
     59     WAIT_SET,
     60 
     61     // "Private" types (not exposed via the public interface):
     62     PLATFORM_HANDLE = -1,
     63   };
     64 
     65   // All Dispatchers must minimally implement these methods.
     66 
     67   virtual Type GetType() const = 0;
     68   virtual MojoResult Close() = 0;
     69 
     70   ///////////// Watch API ////////////////////
     71 
     72   virtual MojoResult Watch(MojoHandleSignals signals,
     73                            const Watcher::WatchCallback& callback,
     74                            uintptr_t context);
     75 
     76   virtual MojoResult CancelWatch(uintptr_t context);
     77 
     78   ///////////// Message pipe API /////////////
     79 
     80   virtual MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message,
     81                                   MojoWriteMessageFlags flags);
     82 
     83   virtual MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message,
     84                                  uint32_t* num_bytes,
     85                                  MojoHandle* handles,
     86                                  uint32_t* num_handles,
     87                                  MojoReadMessageFlags flags,
     88                                  bool read_any_size);
     89 
     90   ///////////// Shared buffer API /////////////
     91 
     92   // |options| may be null. |new_dispatcher| must not be null, but
     93   // |*new_dispatcher| should be null (and will contain the dispatcher for the
     94   // new handle on success).
     95   virtual MojoResult DuplicateBufferHandle(
     96       const MojoDuplicateBufferHandleOptions* options,
     97       scoped_refptr<Dispatcher>* new_dispatcher);
     98 
     99   virtual MojoResult MapBuffer(
    100       uint64_t offset,
    101       uint64_t num_bytes,
    102       MojoMapBufferFlags flags,
    103       std::unique_ptr<PlatformSharedBufferMapping>* mapping);
    104 
    105   ///////////// Data pipe consumer API /////////////
    106 
    107   virtual MojoResult ReadData(void* elements,
    108                               uint32_t* num_bytes,
    109                               MojoReadDataFlags flags);
    110 
    111   virtual MojoResult BeginReadData(const void** buffer,
    112                                    uint32_t* buffer_num_bytes,
    113                                    MojoReadDataFlags flags);
    114 
    115   virtual MojoResult EndReadData(uint32_t num_bytes_read);
    116 
    117   ///////////// Data pipe producer API /////////////
    118 
    119   virtual MojoResult WriteData(const void* elements,
    120                                uint32_t* num_bytes,
    121                                MojoWriteDataFlags flags);
    122 
    123   virtual MojoResult BeginWriteData(void** buffer,
    124                                     uint32_t* buffer_num_bytes,
    125                                     MojoWriteDataFlags flags);
    126 
    127   virtual MojoResult EndWriteData(uint32_t num_bytes_written);
    128 
    129   ///////////// Wait set API /////////////
    130 
    131   // Adds a dispatcher to wait on. When the dispatcher satisfies |signals|, it
    132   // will be returned in the next call to |GetReadyDispatchers()|. If
    133   // |dispatcher| has been added, it must be removed before adding again,
    134   // otherwise |MOJO_RESULT_ALREADY_EXISTS| will be returned.
    135   virtual MojoResult AddWaitingDispatcher(
    136       const scoped_refptr<Dispatcher>& dispatcher,
    137       MojoHandleSignals signals,
    138       uintptr_t context);
    139 
    140   // Removes a dispatcher to wait on. If |dispatcher| has not been added,
    141   // |MOJO_RESULT_NOT_FOUND| will be returned.
    142   virtual MojoResult RemoveWaitingDispatcher(
    143       const scoped_refptr<Dispatcher>& dispatcher);
    144 
    145   // Returns a set of ready dispatchers. |*count| is the maximum number of
    146   // dispatchers to return, and will contain the number of dispatchers returned
    147   // in |dispatchers| on completion.
    148   virtual MojoResult GetReadyDispatchers(uint32_t* count,
    149                                          DispatcherVector* dispatchers,
    150                                          MojoResult* results,
    151                                          uintptr_t* contexts);
    152 
    153   ///////////// General-purpose API for all handle types /////////
    154 
    155   // Gets the current handle signals state. (The default implementation simply
    156   // returns a default-constructed |HandleSignalsState|, i.e., no signals
    157   // satisfied or satisfiable.) Note: The state is subject to change from other
    158   // threads.
    159   virtual HandleSignalsState GetHandleSignalsState() const;
    160 
    161   // Adds an awakable to this dispatcher, which will be woken up when this
    162   // object changes state to satisfy |signals| with context |context|. It will
    163   // also be woken up when it becomes impossible for the object to ever satisfy
    164   // |signals| with a suitable error status.
    165   //
    166   // If |signals_state| is non-null, on *failure* |*signals_state| will be set
    167   // to the current handle signals state (on success, it is left untouched).
    168   //
    169   // Returns:
    170   //  - |MOJO_RESULT_OK| if the awakable was added;
    171   //  - |MOJO_RESULT_ALREADY_EXISTS| if |signals| is already satisfied;
    172   //  - |MOJO_RESULT_INVALID_ARGUMENT| if the dispatcher has been closed; and
    173   //  - |MOJO_RESULT_FAILED_PRECONDITION| if it is not (or no longer) possible
    174   //    that |signals| will ever be satisfied.
    175   virtual MojoResult AddAwakable(Awakable* awakable,
    176                                  MojoHandleSignals signals,
    177                                  uintptr_t context,
    178                                  HandleSignalsState* signals_state);
    179 
    180   // Removes an awakable from this dispatcher. (It is valid to call this
    181   // multiple times for the same |awakable| on the same object, so long as
    182   // |AddAwakable()| was called at most once.) If |signals_state| is non-null,
    183   // |*signals_state| will be set to the current handle signals state.
    184   virtual void RemoveAwakable(Awakable* awakable,
    185                               HandleSignalsState* signals_state);
    186 
    187   // Informs the caller of the total serialized size (in bytes) and the total
    188   // number of platform handles and ports needed to transfer this dispatcher
    189   // across a message pipe.
    190   //
    191   // Must eventually be followed by a call to EndSerializeAndClose(). Note that
    192   // StartSerialize() and EndSerialize() are always called in sequence, and
    193   // only between calls to BeginTransit() and either (but not both)
    194   // CompleteTransitAndClose() or CancelTransit().
    195   //
    196   // For this reason it is IMPERATIVE that the implementation ensure a
    197   // consistent serializable state between BeginTransit() and
    198   // CompleteTransitAndClose()/CancelTransit().
    199   virtual void StartSerialize(uint32_t* num_bytes,
    200                               uint32_t* num_ports,
    201                               uint32_t* num_platform_handles);
    202 
    203   // Serializes this dispatcher into |destination|, |ports|, and |handles|.
    204   // Returns true iff successful, false otherwise. In either case the dispatcher
    205   // will close.
    206   //
    207   // NOTE: Transit MAY still fail after this call returns. Implementations
    208   // should not assume PlatformHandle ownership has transferred until
    209   // CompleteTransitAndClose() is called. In other words, if CancelTransit() is
    210   // called, the implementation should retain its PlatformHandles in working
    211   // condition.
    212   virtual bool EndSerialize(void* destination,
    213                             ports::PortName* ports,
    214                             PlatformHandle* handles);
    215 
    216   // Does whatever is necessary to begin transit of the dispatcher.  This
    217   // should return |true| if transit is OK, or false if the underlying resource
    218   // is deemed busy by the implementation.
    219   virtual bool BeginTransit();
    220 
    221   // Does whatever is necessary to complete transit of the dispatcher, including
    222   // closure. This is only called upon successfully transmitting an outgoing
    223   // message containing this serialized dispatcher.
    224   virtual void CompleteTransitAndClose();
    225 
    226   // Does whatever is necessary to cancel transit of the dispatcher. The
    227   // dispatcher should remain in a working state and resume normal operation.
    228   virtual void CancelTransit();
    229 
    230   // Deserializes a specific dispatcher type from an incoming message.
    231   static scoped_refptr<Dispatcher> Deserialize(
    232       Type type,
    233       const void* bytes,
    234       size_t num_bytes,
    235       const ports::PortName* ports,
    236       size_t num_ports,
    237       PlatformHandle* platform_handles,
    238       size_t num_platform_handles);
    239 
    240  protected:
    241   friend class base::RefCountedThreadSafe<Dispatcher>;
    242 
    243   Dispatcher();
    244   virtual ~Dispatcher();
    245 
    246   DISALLOW_COPY_AND_ASSIGN(Dispatcher);
    247 };
    248 
    249 // So logging macros and |DCHECK_EQ()|, etc. work.
    250 MOJO_SYSTEM_IMPL_EXPORT inline std::ostream& operator<<(std::ostream& out,
    251                                                         Dispatcher::Type type) {
    252   return out << static_cast<int>(type);
    253 }
    254 
    255 }  // namespace edk
    256 }  // namespace mojo
    257 
    258 #endif  // MOJO_EDK_SYSTEM_DISPATCHER_H_
    259