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_PUBLIC_CPP_SYSTEM_CORE_H_
6#define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
7
8#include <assert.h>
9#include <stddef.h>
10
11#include <limits>
12
13#include "mojo/public/c/system/core.h"
14#include "mojo/public/c/system/system_export.h"
15#include "mojo/public/cpp/system/macros.h"
16
17namespace mojo {
18
19// OVERVIEW
20//
21// |Handle| and |...Handle|:
22//
23// |Handle| is a simple, copyable wrapper for the C type |MojoHandle| (which is
24// just an integer). Its purpose is to increase type-safety, not provide
25// lifetime management. For the same purpose, we have trivial *subclasses* of
26// |Handle|, e.g., |MessagePipeHandle| and |DataPipeProducerHandle|. |Handle|
27// and its subclasses impose *no* extra overhead over using |MojoHandle|s
28// directly.
29//
30// Note that though we provide constructors for |Handle|/|...Handle| from a
31// |MojoHandle|, we do not provide, e.g., a constructor for |MessagePipeHandle|
32// from a |Handle|. This is for type safety: If we did, you'd then be able to
33// construct a |MessagePipeHandle| from, e.g., a |DataPipeProducerHandle| (since
34// it's a |Handle|).
35//
36// |ScopedHandleBase| and |Scoped...Handle|:
37//
38// |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle
39// types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped
40// wrapper for a |T*|). It provides lifetime management, closing its owned
41// handle on destruction. It also provides (emulated) move semantics, again
42// along the lines of C++11's |unique_ptr| (and exactly like Chromium's
43// |scoped_ptr|).
44//
45// |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|.
46// Similarly, |ScopedMessagePipeHandle| is just a
47// |ScopedHandleBase<MessagePipeHandle>|. Etc. Note that a
48// |ScopedMessagePipeHandle| is *not* a (subclass of) |ScopedHandle|.
49//
50// Wrapper functions:
51//
52// We provide simple wrappers for the |Mojo...()| functions (in
53// mojo/public/c/system/core.h -- see that file for details on individual
54// functions).
55//
56// The general guideline is functions that imply ownership transfer of a handle
57// should take (or produce) an appropriate |Scoped...Handle|, while those that
58// don't take a |...Handle|. For example, |CreateMessagePipe()| has two
59// |ScopedMessagePipe| "out" parameters, whereas |Wait()| and |WaitMany()| take
60// |Handle| parameters. Some, have both: e.g., |DuplicatedBuffer()| takes a
61// suitable (unscoped) handle (e.g., |SharedBufferHandle|) "in" parameter and
62// produces a suitable scoped handle (e.g., |ScopedSharedBufferHandle| a.k.a.
63// |ScopedHandleBase<SharedBufferHandle>|) as an "out" parameter.
64//
65// An exception are some of the |...Raw()| functions. E.g., |CloseRaw()| takes a
66// |Handle|, leaving the user to discard the handle.
67//
68// More significantly, |WriteMessageRaw()| exposes the full API complexity of
69// |MojoWriteMessage()| (but doesn't require any extra overhead). It takes a raw
70// array of |Handle|s as input, and takes ownership of them (i.e., invalidates
71// them) on *success* (but not on failure). There are a number of reasons for
72// this. First, C++03 |std::vector|s cannot contain the move-only
73// |Scoped...Handle|s. Second, |std::vector|s impose extra overhead
74// (necessitating heap-allocation of the buffer). Third, |std::vector|s wouldn't
75// provide the desired level of flexibility/safety: a vector of handles would
76// have to be all of the same type (probably |Handle|/|ScopedHandle|). Fourth,
77// it's expected to not be used directly, but instead be used by generated
78// bindings.
79//
80// Other |...Raw()| functions expose similar rough edges, e.g., dealing with raw
81// pointers (and lengths) instead of taking |std::vector|s or similar.
82
83// Standalone functions --------------------------------------------------------
84
85inline MojoTimeTicks GetTimeTicksNow() {
86  return MojoGetTimeTicksNow();
87}
88
89// ScopedHandleBase ------------------------------------------------------------
90
91// Scoper for the actual handle types defined further below. It's move-only,
92// like the C++11 |unique_ptr|.
93template <class HandleType>
94class ScopedHandleBase {
95  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue)
96
97 public:
98  ScopedHandleBase() {}
99  explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
100  ~ScopedHandleBase() { CloseIfNecessary(); }
101
102  template <class CompatibleHandleType>
103  explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
104      : handle_(other.release()) {
105  }
106
107  // Move-only constructor and operator=.
108  ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
109  ScopedHandleBase& operator=(RValue other) {
110    if (other.object != this) {
111      CloseIfNecessary();
112      handle_ = other.object->release();
113    }
114    return *this;
115  }
116
117  const HandleType& get() const { return handle_; }
118
119  template <typename PassedHandleType>
120  static ScopedHandleBase<HandleType> From(
121      ScopedHandleBase<PassedHandleType> other) {
122    MOJO_COMPILE_ASSERT(
123        sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))),
124        HandleType_is_not_a_subtype_of_PassedHandleType);
125    return ScopedHandleBase<HandleType>(
126        static_cast<HandleType>(other.release().value()));
127  }
128
129  void swap(ScopedHandleBase& other) {
130    handle_.swap(other.handle_);
131  }
132
133  HandleType release() MOJO_WARN_UNUSED_RESULT {
134    HandleType rv;
135    rv.swap(handle_);
136    return rv;
137  }
138
139  void reset(HandleType handle = HandleType()) {
140    CloseIfNecessary();
141    handle_ = handle;
142  }
143
144  bool is_valid() const {
145    return handle_.is_valid();
146  }
147
148 private:
149  void CloseIfNecessary() {
150    if (!handle_.is_valid())
151      return;
152    MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
153    assert(result == MOJO_RESULT_OK);
154  }
155
156  HandleType handle_;
157};
158
159template <typename HandleType>
160inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
161  return ScopedHandleBase<HandleType>(handle);
162}
163
164// Handle ----------------------------------------------------------------------
165
166const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
167
168// Wrapper base class for |MojoHandle|.
169class Handle {
170 public:
171  Handle() : value_(kInvalidHandleValue) {}
172  explicit Handle(MojoHandle value) : value_(value) {}
173  ~Handle() {}
174
175  void swap(Handle& other) {
176    MojoHandle temp = value_;
177    value_ = other.value_;
178    other.value_ = temp;
179  }
180
181  bool is_valid() const {
182    return value_ != kInvalidHandleValue;
183  }
184
185  MojoHandle value() const { return value_; }
186  MojoHandle* mutable_value() { return &value_; }
187  void set_value(MojoHandle value) { value_ = value; }
188
189 private:
190  MojoHandle value_;
191
192  // Copying and assignment allowed.
193};
194
195// Should have zero overhead.
196MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
197                    bad_size_for_cpp_Handle);
198
199// The scoper should also impose no more overhead.
200typedef ScopedHandleBase<Handle> ScopedHandle;
201MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
202                    bad_size_for_cpp_ScopedHandle);
203
204inline MojoResult Wait(const Handle& handle,
205                       MojoHandleSignals signals,
206                       MojoDeadline deadline) {
207  return MojoWait(handle.value(), signals, deadline);
208}
209
210// |HandleVectorType| and |FlagsVectorType| should be similar enough to
211// |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively:
212//  - They should have a (const) |size()| method that returns an unsigned type.
213//  - They must provide contiguous storage, with access via (const) reference to
214//    that storage provided by a (const) |operator[]()| (by reference).
215template <class HandleVectorType, class FlagsVectorType>
216inline MojoResult WaitMany(const HandleVectorType& handles,
217                           const FlagsVectorType& signals,
218                           MojoDeadline deadline) {
219  if (signals.size() != handles.size())
220    return MOJO_RESULT_INVALID_ARGUMENT;
221  if (handles.size() > std::numeric_limits<uint32_t>::max())
222    return MOJO_RESULT_OUT_OF_RANGE;
223
224  if (handles.size() == 0)
225    return MojoWaitMany(NULL, NULL, 0, deadline);
226
227  const Handle& first_handle = handles[0];
228  const MojoHandleSignals& first_signals = signals[0];
229  return MojoWaitMany(
230      reinterpret_cast<const MojoHandle*>(&first_handle),
231      reinterpret_cast<const MojoHandleSignals*>(&first_signals),
232      static_cast<uint32_t>(handles.size()),
233      deadline);
234}
235
236// |Close()| takes ownership of the handle, since it'll invalidate it.
237// Note: There's nothing to do, since the argument will be destroyed when it
238// goes out of scope.
239template <class HandleType>
240inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
241
242// Most users should typically use |Close()| (above) instead.
243inline MojoResult CloseRaw(Handle handle) {
244  return MojoClose(handle.value());
245}
246
247// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
248// etc.
249inline bool operator<(const Handle& a, const Handle& b) {
250  return a.value() < b.value();
251}
252
253// MessagePipeHandle -----------------------------------------------------------
254
255class MessagePipeHandle : public Handle {
256 public:
257  MessagePipeHandle() {}
258  explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
259
260  // Copying and assignment allowed.
261};
262
263MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
264                    bad_size_for_cpp_MessagePipeHandle);
265
266typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
267MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
268                        sizeof(MessagePipeHandle),
269                    bad_size_for_cpp_ScopedMessagePipeHandle);
270
271inline MojoResult CreateMessagePipe(const MojoCreateMessagePipeOptions* options,
272                                    ScopedMessagePipeHandle* message_pipe0,
273                                    ScopedMessagePipeHandle* message_pipe1) {
274  assert(message_pipe0);
275  assert(message_pipe1);
276  MessagePipeHandle handle0;
277  MessagePipeHandle handle1;
278  MojoResult rv = MojoCreateMessagePipe(options,
279                                        handle0.mutable_value(),
280                                        handle1.mutable_value());
281  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
282  // will be used).
283  message_pipe0->reset(handle0);
284  message_pipe1->reset(handle1);
285  return rv;
286}
287
288// These "raw" versions fully expose the underlying API, but don't help with
289// ownership of handles (especially when writing messages).
290// TODO(vtl): Write "baked" versions.
291inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe,
292                                  const void* bytes,
293                                  uint32_t num_bytes,
294                                  const MojoHandle* handles,
295                                  uint32_t num_handles,
296                                  MojoWriteMessageFlags flags) {
297  return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles,
298                          num_handles, flags);
299}
300
301inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
302                                 void* bytes,
303                                 uint32_t* num_bytes,
304                                 MojoHandle* handles,
305                                 uint32_t* num_handles,
306                                 MojoReadMessageFlags flags) {
307  return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles,
308                         num_handles, flags);
309}
310
311// A wrapper class that automatically creates a message pipe and owns both
312// handles.
313class MessagePipe {
314 public:
315  MessagePipe();
316  explicit MessagePipe(const MojoCreateMessagePipeOptions& options);
317  ~MessagePipe();
318
319  ScopedMessagePipeHandle handle0;
320  ScopedMessagePipeHandle handle1;
321};
322
323inline MessagePipe::MessagePipe() {
324  MojoResult result MOJO_ALLOW_UNUSED =
325      CreateMessagePipe(NULL, &handle0, &handle1);
326  assert(result == MOJO_RESULT_OK);
327}
328
329inline MessagePipe::MessagePipe(const MojoCreateMessagePipeOptions& options) {
330  MojoResult result MOJO_ALLOW_UNUSED =
331      CreateMessagePipe(&options, &handle0, &handle1);
332  assert(result == MOJO_RESULT_OK);
333}
334
335inline MessagePipe::~MessagePipe() {
336}
337
338// DataPipeProducerHandle and DataPipeConsumerHandle ---------------------------
339
340class DataPipeProducerHandle : public Handle {
341 public:
342  DataPipeProducerHandle() {}
343  explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
344
345  // Copying and assignment allowed.
346};
347
348MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
349                    bad_size_for_cpp_DataPipeProducerHandle);
350
351typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
352MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
353                        sizeof(DataPipeProducerHandle),
354                    bad_size_for_cpp_ScopedDataPipeProducerHandle);
355
356class DataPipeConsumerHandle : public Handle {
357 public:
358  DataPipeConsumerHandle() {}
359  explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
360
361  // Copying and assignment allowed.
362};
363
364MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
365                    bad_size_for_cpp_DataPipeConsumerHandle);
366
367typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
368MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
369                        sizeof(DataPipeConsumerHandle),
370                    bad_size_for_cpp_ScopedDataPipeConsumerHandle);
371
372inline MojoResult CreateDataPipe(
373    const MojoCreateDataPipeOptions* options,
374    ScopedDataPipeProducerHandle* data_pipe_producer,
375    ScopedDataPipeConsumerHandle* data_pipe_consumer) {
376  assert(data_pipe_producer);
377  assert(data_pipe_consumer);
378  DataPipeProducerHandle producer_handle;
379  DataPipeConsumerHandle consumer_handle;
380  MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(),
381                                     consumer_handle.mutable_value());
382  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
383  // will be used).
384  data_pipe_producer->reset(producer_handle);
385  data_pipe_consumer->reset(consumer_handle);
386  return rv;
387}
388
389inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
390                               const void* elements,
391                               uint32_t* num_bytes,
392                               MojoWriteDataFlags flags) {
393  return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
394}
395
396inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
397                                    void** buffer,
398                                    uint32_t* buffer_num_bytes,
399                                    MojoWriteDataFlags flags) {
400  return MojoBeginWriteData(data_pipe_producer.value(), buffer,
401                            buffer_num_bytes, flags);
402}
403
404inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
405                                  uint32_t num_bytes_written) {
406  return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
407}
408
409inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
410                              void* elements,
411                              uint32_t* num_bytes,
412                              MojoReadDataFlags flags) {
413  return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
414}
415
416inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
417                                   const void** buffer,
418                                   uint32_t* buffer_num_bytes,
419                                   MojoReadDataFlags flags) {
420  return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes,
421                           flags);
422}
423
424inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
425                                 uint32_t num_bytes_read) {
426  return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
427}
428
429// A wrapper class that automatically creates a data pipe and owns both handles.
430// TODO(vtl): Make an even more friendly version? (Maybe templatized for a
431// particular type instead of some "element"? Maybe functions that take
432// vectors?)
433class DataPipe {
434 public:
435  DataPipe();
436  explicit DataPipe(const MojoCreateDataPipeOptions& options);
437  ~DataPipe();
438
439  ScopedDataPipeProducerHandle producer_handle;
440  ScopedDataPipeConsumerHandle consumer_handle;
441};
442
443inline DataPipe::DataPipe() {
444  MojoResult result MOJO_ALLOW_UNUSED =
445      CreateDataPipe(NULL, &producer_handle, &consumer_handle);
446  assert(result == MOJO_RESULT_OK);
447}
448
449inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
450  MojoResult result MOJO_ALLOW_UNUSED =
451      CreateDataPipe(&options, &producer_handle, &consumer_handle);
452  assert(result == MOJO_RESULT_OK);
453}
454
455inline DataPipe::~DataPipe() {
456}
457
458// SharedBufferHandle ----------------------------------------------------------
459
460class SharedBufferHandle : public Handle {
461 public:
462  SharedBufferHandle() {}
463  explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
464
465  // Copying and assignment allowed.
466};
467
468MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
469                    bad_size_for_cpp_SharedBufferHandle);
470
471typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
472MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
473                        sizeof(SharedBufferHandle),
474                    bad_size_for_cpp_ScopedSharedBufferHandle);
475
476inline MojoResult CreateSharedBuffer(
477    const MojoCreateSharedBufferOptions* options,
478    uint64_t num_bytes,
479    ScopedSharedBufferHandle* shared_buffer) {
480  assert(shared_buffer);
481  SharedBufferHandle handle;
482  MojoResult rv = MojoCreateSharedBuffer(options, num_bytes,
483                                         handle.mutable_value());
484  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
485  // will be used).
486  shared_buffer->reset(handle);
487  return rv;
488}
489
490// TODO(vtl): This (and also the functions below) are templatized to allow for
491// future/other buffer types. A bit "safer" would be to overload this function
492// manually. (The template enforces that the in and out handles to be of the
493// same type.)
494template <class BufferHandleType>
495inline MojoResult DuplicateBuffer(
496    BufferHandleType buffer,
497    const MojoDuplicateBufferHandleOptions* options,
498    ScopedHandleBase<BufferHandleType>* new_buffer) {
499  assert(new_buffer);
500  BufferHandleType handle;
501  MojoResult rv = MojoDuplicateBufferHandle(
502      buffer.value(), options, handle.mutable_value());
503  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
504  // will be used).
505  new_buffer->reset(handle);
506  return rv;
507}
508
509template <class BufferHandleType>
510inline MojoResult MapBuffer(BufferHandleType buffer,
511                            uint64_t offset,
512                            uint64_t num_bytes,
513                            void** pointer,
514                            MojoMapBufferFlags flags) {
515  assert(buffer.is_valid());
516  return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags);
517}
518
519inline MojoResult UnmapBuffer(void* pointer) {
520  assert(pointer);
521  return MojoUnmapBuffer(pointer);
522}
523
524// A wrapper class that automatically creates a shared buffer and owns the
525// handle.
526class SharedBuffer {
527 public:
528  explicit SharedBuffer(uint64_t num_bytes);
529  SharedBuffer(uint64_t num_bytes,
530               const MojoCreateSharedBufferOptions& options);
531  ~SharedBuffer();
532
533  ScopedSharedBufferHandle handle;
534};
535
536inline SharedBuffer::SharedBuffer(uint64_t num_bytes) {
537  MojoResult result MOJO_ALLOW_UNUSED =
538      CreateSharedBuffer(NULL, num_bytes, &handle);
539  assert(result == MOJO_RESULT_OK);
540}
541
542inline SharedBuffer::SharedBuffer(
543    uint64_t num_bytes,
544    const MojoCreateSharedBufferOptions& options) {
545  MojoResult result MOJO_ALLOW_UNUSED =
546      CreateSharedBuffer(&options, num_bytes, &handle);
547  assert(result == MOJO_RESULT_OK);
548}
549
550inline SharedBuffer::~SharedBuffer() {
551}
552
553}  // namespace mojo
554
555#endif  // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
556