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_SYSTEM_DATA_PIPE_H_
      6 #define MOJO_SYSTEM_DATA_PIPE_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "base/macros.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/synchronization/lock.h"
     14 #include "mojo/public/c/system/data_pipe.h"
     15 #include "mojo/public/c/system/types.h"
     16 #include "mojo/system/handle_signals_state.h"
     17 #include "mojo/system/system_impl_export.h"
     18 
     19 namespace mojo {
     20 namespace system {
     21 
     22 class Waiter;
     23 class WaiterList;
     24 
     25 // |DataPipe| is a base class for secondary objects implementing data pipes,
     26 // similar to |MessagePipe| (see the explanatory comment in core.cc). It is
     27 // typically owned by the dispatcher(s) corresponding to the local endpoints.
     28 // Its subclasses implement the three cases: local producer and consumer, local
     29 // producer and remote consumer, and remote producer and local consumer. This
     30 // class is thread-safe.
     31 class MOJO_SYSTEM_IMPL_EXPORT DataPipe :
     32     public base::RefCountedThreadSafe<DataPipe> {
     33  public:
     34   // The default options for |MojoCreateDataPipe()|. (Real uses should obtain
     35   // this via |ValidateCreateOptions()| with a null |in_options|; this is
     36   // exposed directly for testing convenience.)
     37   static const MojoCreateDataPipeOptions kDefaultCreateOptions;
     38 
     39   // Validates and/or sets default options for |MojoCreateDataPipeOptions|. If
     40   // non-null, |in_options| must point to a struct of at least
     41   // |in_options->struct_size| bytes. |out_options| must point to a (current)
     42   // |MojoCreateDataPipeOptions| and will be entirely overwritten on success (it
     43   // may be partly overwritten on failure).
     44   static MojoResult ValidateCreateOptions(
     45       const MojoCreateDataPipeOptions* in_options,
     46       MojoCreateDataPipeOptions* out_options);
     47 
     48   // These are called by the producer dispatcher to implement its methods of
     49   // corresponding names.
     50   void ProducerCancelAllWaiters();
     51   void ProducerClose();
     52   // This does not validate its arguments, except to check that |*num_bytes| is
     53   // a multiple of |element_num_bytes_|.
     54   MojoResult ProducerWriteData(const void* elements,
     55                                uint32_t* num_bytes,
     56                                bool all_or_none);
     57   // This does not validate its arguments.
     58   MojoResult ProducerBeginWriteData(void** buffer,
     59                                     uint32_t* buffer_num_bytes,
     60                                     bool all_or_none);
     61   MojoResult ProducerEndWriteData(uint32_t num_bytes_written);
     62   MojoResult ProducerAddWaiter(Waiter* waiter,
     63                                MojoHandleSignals signals,
     64                                uint32_t context);
     65   void ProducerRemoveWaiter(Waiter* waiter);
     66   bool ProducerIsBusy() const;
     67 
     68   // These are called by the consumer dispatcher to implement its methods of
     69   // corresponding names.
     70   void ConsumerCancelAllWaiters();
     71   void ConsumerClose();
     72   // This does not validate its arguments, except to check that |*num_bytes| is
     73   // a multiple of |element_num_bytes_|.
     74   MojoResult ConsumerReadData(void* elements,
     75                               uint32_t* num_bytes,
     76                               bool all_or_none);
     77   MojoResult ConsumerDiscardData(uint32_t* num_bytes,
     78                                  bool all_or_none);
     79   MojoResult ConsumerQueryData(uint32_t* num_bytes);
     80   // This does not validate its arguments.
     81   MojoResult ConsumerBeginReadData(const void** buffer,
     82                                    uint32_t* buffer_num_bytes,
     83                                    bool all_or_none);
     84   MojoResult ConsumerEndReadData(uint32_t num_bytes_read);
     85   MojoResult ConsumerAddWaiter(Waiter* waiter,
     86                                MojoHandleSignals signals,
     87                                uint32_t context);
     88   void ConsumerRemoveWaiter(Waiter* waiter);
     89   bool ConsumerIsBusy() const;
     90 
     91  protected:
     92   DataPipe(bool has_local_producer,
     93            bool has_local_consumer,
     94            const MojoCreateDataPipeOptions& validated_options);
     95 
     96   friend class base::RefCountedThreadSafe<DataPipe>;
     97   virtual ~DataPipe();
     98 
     99   virtual void ProducerCloseImplNoLock() = 0;
    100   // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
    101   virtual MojoResult ProducerWriteDataImplNoLock(const void* elements,
    102                                                  uint32_t* num_bytes,
    103                                                  bool all_or_none) = 0;
    104   virtual MojoResult ProducerBeginWriteDataImplNoLock(
    105       void** buffer,
    106       uint32_t* buffer_num_bytes,
    107       bool all_or_none) = 0;
    108   virtual MojoResult ProducerEndWriteDataImplNoLock(
    109       uint32_t num_bytes_written) = 0;
    110   // Note: A producer should not be writable during a two-phase write.
    111   virtual HandleSignalsState ProducerGetHandleSignalsStateNoLock() const = 0;
    112 
    113   virtual void ConsumerCloseImplNoLock() = 0;
    114   // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
    115   virtual MojoResult ConsumerReadDataImplNoLock(void* elements,
    116                                                 uint32_t* num_bytes,
    117                                                 bool all_or_none) = 0;
    118   virtual MojoResult ConsumerDiscardDataImplNoLock(uint32_t* num_bytes,
    119                                                    bool all_or_none) = 0;
    120   // |*num_bytes| will be a nonzero multiple of |element_num_bytes_|.
    121   virtual MojoResult ConsumerQueryDataImplNoLock(uint32_t* num_bytes) = 0;
    122   virtual MojoResult ConsumerBeginReadDataImplNoLock(const void** buffer,
    123                                                      uint32_t* buffer_num_bytes,
    124                                                      bool all_or_none) = 0;
    125   virtual MojoResult ConsumerEndReadDataImplNoLock(uint32_t num_bytes_read) = 0;
    126   // Note: A consumer should not be writable during a two-phase read.
    127   virtual HandleSignalsState ConsumerGetHandleSignalsStateNoLock() const = 0;
    128 
    129   // Thread-safe and fast (they don't take the lock):
    130   bool may_discard() const { return may_discard_; }
    131   size_t element_num_bytes() const { return element_num_bytes_; }
    132   size_t capacity_num_bytes() const { return capacity_num_bytes_; }
    133 
    134   // Must be called under lock.
    135   bool producer_open_no_lock() const {
    136     lock_.AssertAcquired();
    137     return producer_open_;
    138   }
    139   bool consumer_open_no_lock() const {
    140     lock_.AssertAcquired();
    141     return consumer_open_;
    142   }
    143   uint32_t producer_two_phase_max_num_bytes_written_no_lock() const {
    144     lock_.AssertAcquired();
    145     return producer_two_phase_max_num_bytes_written_;
    146   }
    147   uint32_t consumer_two_phase_max_num_bytes_read_no_lock() const {
    148     lock_.AssertAcquired();
    149     return consumer_two_phase_max_num_bytes_read_;
    150   }
    151   void set_producer_two_phase_max_num_bytes_written_no_lock(
    152       uint32_t num_bytes) {
    153     lock_.AssertAcquired();
    154     producer_two_phase_max_num_bytes_written_ = num_bytes;
    155   }
    156   void set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes) {
    157     lock_.AssertAcquired();
    158     consumer_two_phase_max_num_bytes_read_ = num_bytes;
    159   }
    160   bool producer_in_two_phase_write_no_lock() const {
    161     lock_.AssertAcquired();
    162     return producer_two_phase_max_num_bytes_written_ > 0;
    163   }
    164   bool consumer_in_two_phase_read_no_lock() const {
    165     lock_.AssertAcquired();
    166     return consumer_two_phase_max_num_bytes_read_ > 0;
    167   }
    168 
    169  private:
    170   void AwakeProducerWaitersForStateChangeNoLock(
    171       const HandleSignalsState& new_producer_state);
    172   void AwakeConsumerWaitersForStateChangeNoLock(
    173       const HandleSignalsState& new_consumer_state);
    174 
    175   bool has_local_producer_no_lock() const {
    176     lock_.AssertAcquired();
    177     return !!producer_waiter_list_;
    178   }
    179   bool has_local_consumer_no_lock() const {
    180     lock_.AssertAcquired();
    181     return !!consumer_waiter_list_;
    182   }
    183 
    184   const bool may_discard_;
    185   const size_t element_num_bytes_;
    186   const size_t capacity_num_bytes_;
    187 
    188   mutable base::Lock lock_;  // Protects the following members.
    189   // *Known* state of producer or consumer.
    190   bool producer_open_;
    191   bool consumer_open_;
    192   // Non-null only if the producer or consumer, respectively, is local.
    193   scoped_ptr<WaiterList> producer_waiter_list_;
    194   scoped_ptr<WaiterList> consumer_waiter_list_;
    195   // These are nonzero if and only if a two-phase write/read is in progress.
    196   uint32_t producer_two_phase_max_num_bytes_written_;
    197   uint32_t consumer_two_phase_max_num_bytes_read_;
    198 
    199   DISALLOW_COPY_AND_ASSIGN(DataPipe);
    200 };
    201 
    202 }  // namespace system
    203 }  // namespace mojo
    204 
    205 #endif  // MOJO_SYSTEM_DATA_PIPE_H_
    206