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_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 
     17 namespace 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 
     85 inline 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|.
     93 template <class HandleType>
     94 class 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 
    159 template <typename HandleType>
    160 inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
    161   return ScopedHandleBase<HandleType>(handle);
    162 }
    163 
    164 // Handle ----------------------------------------------------------------------
    165 
    166 const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
    167 
    168 // Wrapper base class for |MojoHandle|.
    169 class 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.
    196 MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
    197                     bad_size_for_cpp_Handle);
    198 
    199 // The scoper should also impose no more overhead.
    200 typedef ScopedHandleBase<Handle> ScopedHandle;
    201 MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
    202                     bad_size_for_cpp_ScopedHandle);
    203 
    204 inline 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).
    215 template <class HandleVectorType, class FlagsVectorType>
    216 inline 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.
    239 template <class HandleType>
    240 inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
    241 
    242 // Most users should typically use |Close()| (above) instead.
    243 inline 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.
    249 inline bool operator<(const Handle& a, const Handle& b) {
    250   return a.value() < b.value();
    251 }
    252 
    253 // MessagePipeHandle -----------------------------------------------------------
    254 
    255 class MessagePipeHandle : public Handle {
    256  public:
    257   MessagePipeHandle() {}
    258   explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
    259 
    260   // Copying and assignment allowed.
    261 };
    262 
    263 MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
    264                     bad_size_for_cpp_MessagePipeHandle);
    265 
    266 typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
    267 MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
    268                         sizeof(MessagePipeHandle),
    269                     bad_size_for_cpp_ScopedMessagePipeHandle);
    270 
    271 inline 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.
    291 inline 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 
    301 inline 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.
    313 class MessagePipe {
    314  public:
    315   MessagePipe();
    316   explicit MessagePipe(const MojoCreateMessagePipeOptions& options);
    317   ~MessagePipe();
    318 
    319   ScopedMessagePipeHandle handle0;
    320   ScopedMessagePipeHandle handle1;
    321 };
    322 
    323 inline MessagePipe::MessagePipe() {
    324   MojoResult result MOJO_ALLOW_UNUSED =
    325       CreateMessagePipe(NULL, &handle0, &handle1);
    326   assert(result == MOJO_RESULT_OK);
    327 }
    328 
    329 inline MessagePipe::MessagePipe(const MojoCreateMessagePipeOptions& options) {
    330   MojoResult result MOJO_ALLOW_UNUSED =
    331       CreateMessagePipe(&options, &handle0, &handle1);
    332   assert(result == MOJO_RESULT_OK);
    333 }
    334 
    335 inline MessagePipe::~MessagePipe() {
    336 }
    337 
    338 // DataPipeProducerHandle and DataPipeConsumerHandle ---------------------------
    339 
    340 class DataPipeProducerHandle : public Handle {
    341  public:
    342   DataPipeProducerHandle() {}
    343   explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
    344 
    345   // Copying and assignment allowed.
    346 };
    347 
    348 MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
    349                     bad_size_for_cpp_DataPipeProducerHandle);
    350 
    351 typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
    352 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
    353                         sizeof(DataPipeProducerHandle),
    354                     bad_size_for_cpp_ScopedDataPipeProducerHandle);
    355 
    356 class DataPipeConsumerHandle : public Handle {
    357  public:
    358   DataPipeConsumerHandle() {}
    359   explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
    360 
    361   // Copying and assignment allowed.
    362 };
    363 
    364 MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
    365                     bad_size_for_cpp_DataPipeConsumerHandle);
    366 
    367 typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
    368 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
    369                         sizeof(DataPipeConsumerHandle),
    370                     bad_size_for_cpp_ScopedDataPipeConsumerHandle);
    371 
    372 inline 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 
    389 inline 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 
    396 inline 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 
    404 inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
    405                                   uint32_t num_bytes_written) {
    406   return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
    407 }
    408 
    409 inline 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 
    416 inline 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 
    424 inline 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?)
    433 class DataPipe {
    434  public:
    435   DataPipe();
    436   explicit DataPipe(const MojoCreateDataPipeOptions& options);
    437   ~DataPipe();
    438 
    439   ScopedDataPipeProducerHandle producer_handle;
    440   ScopedDataPipeConsumerHandle consumer_handle;
    441 };
    442 
    443 inline DataPipe::DataPipe() {
    444   MojoResult result MOJO_ALLOW_UNUSED =
    445       CreateDataPipe(NULL, &producer_handle, &consumer_handle);
    446   assert(result == MOJO_RESULT_OK);
    447 }
    448 
    449 inline 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 
    455 inline DataPipe::~DataPipe() {
    456 }
    457 
    458 // SharedBufferHandle ----------------------------------------------------------
    459 
    460 class SharedBufferHandle : public Handle {
    461  public:
    462   SharedBufferHandle() {}
    463   explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
    464 
    465   // Copying and assignment allowed.
    466 };
    467 
    468 MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
    469                     bad_size_for_cpp_SharedBufferHandle);
    470 
    471 typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
    472 MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
    473                         sizeof(SharedBufferHandle),
    474                     bad_size_for_cpp_ScopedSharedBufferHandle);
    475 
    476 inline 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.)
    494 template <class BufferHandleType>
    495 inline 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 
    509 template <class BufferHandleType>
    510 inline 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 
    519 inline 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.
    526 class 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 
    536 inline 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 
    542 inline 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 
    550 inline SharedBuffer::~SharedBuffer() {
    551 }
    552 
    553 }  // namespace mojo
    554 
    555 #endif  // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
    556