• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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):
may_discard()130   bool may_discard() const { return may_discard_; }
element_num_bytes()131   size_t element_num_bytes() const { return element_num_bytes_; }
capacity_num_bytes()132   size_t capacity_num_bytes() const { return capacity_num_bytes_; }
133 
134   // Must be called under lock.
producer_open_no_lock()135   bool producer_open_no_lock() const {
136     lock_.AssertAcquired();
137     return producer_open_;
138   }
consumer_open_no_lock()139   bool consumer_open_no_lock() const {
140     lock_.AssertAcquired();
141     return consumer_open_;
142   }
producer_two_phase_max_num_bytes_written_no_lock()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   }
consumer_two_phase_max_num_bytes_read_no_lock()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   }
set_producer_two_phase_max_num_bytes_written_no_lock(uint32_t num_bytes)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   }
set_consumer_two_phase_max_num_bytes_read_no_lock(uint32_t num_bytes)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   }
producer_in_two_phase_write_no_lock()160   bool producer_in_two_phase_write_no_lock() const {
161     lock_.AssertAcquired();
162     return producer_two_phase_max_num_bytes_written_ > 0;
163   }
consumer_in_two_phase_read_no_lock()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 
has_local_producer_no_lock()175   bool has_local_producer_no_lock() const {
176     lock_.AssertAcquired();
177     return !!producer_waiter_list_;
178   }
has_local_consumer_no_lock()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