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