1// Copyright 2014 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// This file provides a C++ wrapping around the Mojo C API for data pipes,
6// replacing the prefix of "Mojo" with a "mojo" namespace, and using more
7// strongly-typed representations of |MojoHandle|s.
8//
9// Please see "mojo/public/c/system/data_pipe.h" for complete documentation of
10// the API.
11
12#ifndef MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_
13#define MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_
14
15#include <stdint.h>
16
17#include "base/compiler_specific.h"
18#include "base/logging.h"
19#include "mojo/public/c/system/data_pipe.h"
20#include "mojo/public/cpp/system/handle.h"
21
22namespace mojo {
23
24// A strongly-typed representation of a |MojoHandle| to the producer end of a
25// data pipe.
26class DataPipeProducerHandle : public Handle {
27 public:
28  DataPipeProducerHandle() {}
29  explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
30
31  // Copying and assignment allowed.
32};
33
34static_assert(sizeof(DataPipeProducerHandle) == sizeof(Handle),
35              "Bad size for C++ DataPipeProducerHandle");
36
37typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
38static_assert(sizeof(ScopedDataPipeProducerHandle) ==
39                  sizeof(DataPipeProducerHandle),
40              "Bad size for C++ ScopedDataPipeProducerHandle");
41
42// A strongly-typed representation of a |MojoHandle| to the consumer end of a
43// data pipe.
44class DataPipeConsumerHandle : public Handle {
45 public:
46  DataPipeConsumerHandle() {}
47  explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
48
49  // Copying and assignment allowed.
50};
51
52static_assert(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
53              "Bad size for C++ DataPipeConsumerHandle");
54
55typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
56static_assert(sizeof(ScopedDataPipeConsumerHandle) ==
57                  sizeof(DataPipeConsumerHandle),
58              "Bad size for C++ ScopedDataPipeConsumerHandle");
59
60// Creates a new data pipe. See |MojoCreateDataPipe()| for complete
61// documentation.
62inline MojoResult CreateDataPipe(
63    const MojoCreateDataPipeOptions* options,
64    ScopedDataPipeProducerHandle* data_pipe_producer,
65    ScopedDataPipeConsumerHandle* data_pipe_consumer) {
66  DCHECK(data_pipe_producer);
67  DCHECK(data_pipe_consumer);
68  DataPipeProducerHandle producer_handle;
69  DataPipeConsumerHandle consumer_handle;
70  MojoResult rv = MojoCreateDataPipe(options,
71                                     producer_handle.mutable_value(),
72                                     consumer_handle.mutable_value());
73  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
74  // will be used).
75  data_pipe_producer->reset(producer_handle);
76  data_pipe_consumer->reset(consumer_handle);
77  return rv;
78}
79
80// Writes to a data pipe. See |MojoWriteData| for complete documentation.
81inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
82                               const void* elements,
83                               uint32_t* num_bytes,
84                               MojoWriteDataFlags flags) {
85  return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
86}
87
88// Begins a two-phase write to a data pipe. See |MojoBeginWriteData()| for
89// complete documentation.
90inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
91                                    void** buffer,
92                                    uint32_t* buffer_num_bytes,
93                                    MojoWriteDataFlags flags) {
94  return MojoBeginWriteData(
95      data_pipe_producer.value(), buffer, buffer_num_bytes, flags);
96}
97
98// Completes a two-phase write to a data pipe. See |MojoEndWriteData()| for
99// complete documentation.
100inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
101                                  uint32_t num_bytes_written) {
102  return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
103}
104
105// Reads from a data pipe. See |MojoReadData()| for complete documentation.
106inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
107                              void* elements,
108                              uint32_t* num_bytes,
109                              MojoReadDataFlags flags) {
110  return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
111}
112
113// Begins a two-phase read from a data pipe. See |MojoBeginReadData()| for
114// complete documentation.
115inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
116                                   const void** buffer,
117                                   uint32_t* buffer_num_bytes,
118                                   MojoReadDataFlags flags) {
119  return MojoBeginReadData(
120      data_pipe_consumer.value(), buffer, buffer_num_bytes, flags);
121}
122
123// Completes a two-phase read from a data pipe. See |MojoEndReadData()| for
124// complete documentation.
125inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
126                                 uint32_t num_bytes_read) {
127  return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
128}
129
130// A wrapper class that automatically creates a data pipe and owns both handles.
131// TODO(vtl): Make an even more friendly version? (Maybe templatized for a
132// particular type instead of some "element"? Maybe functions that take
133// vectors?)
134class DataPipe {
135 public:
136  DataPipe();
137  explicit DataPipe(const MojoCreateDataPipeOptions& options);
138  ~DataPipe();
139
140  ScopedDataPipeProducerHandle producer_handle;
141  ScopedDataPipeConsumerHandle consumer_handle;
142};
143
144inline DataPipe::DataPipe() {
145  MojoResult result =
146      CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
147  ALLOW_UNUSED_LOCAL(result);
148  DCHECK_EQ(MOJO_RESULT_OK, result);
149}
150
151inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
152  MojoResult result =
153      CreateDataPipe(&options, &producer_handle, &consumer_handle);
154  ALLOW_UNUSED_LOCAL(result);
155  DCHECK_EQ(MOJO_RESULT_OK, result);
156}
157
158inline DataPipe::~DataPipe() {
159}
160
161}  // namespace mojo
162
163#endif  // MOJO_PUBLIC_CPP_SYSTEM_DATA_PIPE_H_
164