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_SYSTEM_CORE_CPP_H_
      6 #define MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
      7 
      8 #include <assert.h>
      9 
     10 #include <limits>
     11 
     12 #include "mojo/public/system/core.h"
     13 #include "mojo/public/system/macros.h"
     14 #include "mojo/public/system/system_export.h"
     15 
     16 namespace mojo {
     17 
     18 // ScopedHandleBase ------------------------------------------------------------
     19 
     20 // Scoper for the actual handle types defined further below. It's move-only,
     21 // like the C++11 |unique_ptr|.
     22 template <class HandleType>
     23 class ScopedHandleBase {
     24   MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue);
     25 
     26  public:
     27   ScopedHandleBase() {}
     28   explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
     29   ~ScopedHandleBase() { CloseIfNecessary(); }
     30 
     31   // Move-only constructor and operator=.
     32   ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
     33   ScopedHandleBase& operator=(RValue other) {
     34     handle_ = other.object->release();
     35     return *this;
     36   }
     37 
     38   const HandleType& get() const { return handle_; }
     39 
     40   void swap(ScopedHandleBase& other) {
     41     handle_.swap(other.handle_);
     42   }
     43 
     44   HandleType release() MOJO_WARN_UNUSED_RESULT {
     45     HandleType rv;
     46     rv.swap(handle_);
     47     return rv;
     48   }
     49 
     50   void reset(HandleType handle = HandleType()) {
     51     CloseIfNecessary();
     52     handle_ = handle;
     53   }
     54 
     55   bool is_valid() const {
     56     return handle_.is_valid();
     57   }
     58 
     59  private:
     60   void CloseIfNecessary() {
     61     if (!handle_.is_valid())
     62       return;
     63     MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
     64     assert(result == MOJO_RESULT_OK);
     65   }
     66 
     67   HandleType handle_;
     68 };
     69 
     70 template <typename HandleType>
     71 inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
     72   return ScopedHandleBase<HandleType>(handle);
     73 }
     74 
     75 // Handle ----------------------------------------------------------------------
     76 
     77 const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
     78 
     79 // Wrapper base class for |MojoHandle|.
     80 class Handle {
     81  public:
     82   Handle() : value_(MOJO_HANDLE_INVALID) {}
     83   explicit Handle(MojoHandle value) : value_(value) {}
     84   ~Handle() {}
     85 
     86   void swap(Handle& other) {
     87     MojoHandle temp = value_;
     88     value_ = other.value_;
     89     other.value_ = temp;
     90   }
     91 
     92   bool is_valid() const {
     93     return value_ != MOJO_HANDLE_INVALID;
     94   }
     95 
     96   MojoHandle value() const { return value_; }
     97   MojoHandle* mutable_value() { return &value_; }
     98   void set_value(MojoHandle value) { value_ = value; }
     99 
    100  private:
    101   MojoHandle value_;
    102 
    103   // Copying and assignment allowed.
    104 };
    105 
    106 // Should have zero overhead.
    107 MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
    108                     bad_size_for_cpp_Handle);
    109 
    110 // The scoper should also impose no more overhead.
    111 typedef ScopedHandleBase<Handle> ScopedHandle;
    112 MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
    113                     bad_size_for_cpp_ScopedHandle);
    114 
    115 inline MojoResult Wait(const Handle& handle,
    116                        MojoWaitFlags flags,
    117                        MojoDeadline deadline) {
    118   return MojoWait(handle.value(), flags, deadline);
    119 }
    120 
    121 // |HandleVectorType| and |FlagsVectorType| should be similar enough to
    122 // |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively:
    123 //  - They should have a (const) |size()| method that returns an unsigned type.
    124 //  - They must provide contiguous storage, with access via (const) reference to
    125 //    that storage provided by a (const) |operator[]()| (by reference).
    126 template <class HandleVectorType, class FlagsVectorType>
    127 inline MojoResult WaitMany(const HandleVectorType& handles,
    128                            const FlagsVectorType& flags,
    129                            MojoDeadline deadline) {
    130   if (flags.size() != handles.size())
    131     return MOJO_RESULT_INVALID_ARGUMENT;
    132   if (handles.size() > std::numeric_limits<uint32_t>::max())
    133     return MOJO_RESULT_OUT_OF_RANGE;
    134 
    135   if (handles.size() == 0)
    136     return MojoWaitMany(NULL, NULL, 0, deadline);
    137 
    138   const Handle& first_handle = handles[0];
    139   const MojoWaitFlags& first_flag = flags[0];
    140   return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle),
    141                       reinterpret_cast<const MojoWaitFlags*>(&first_flag),
    142                       static_cast<uint32_t>(handles.size()),
    143                       deadline);
    144 }
    145 
    146 // |Close()| takes ownership of the handle, since it'll invalidate it.
    147 // Note: There's nothing to do, since the argument will be destroyed when it
    148 // goes out of scope.
    149 template <class HandleType>
    150 inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
    151 
    152 // Most users should typically use |Close()| (above) instead.
    153 inline MojoResult CloseRaw(Handle handle) {
    154   return MojoClose(handle.value());
    155 }
    156 
    157 // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
    158 // etc.
    159 inline bool operator<(const Handle& a, const Handle& b) {
    160   return a.value() < b.value();
    161 }
    162 
    163 // MessagePipeHandle -----------------------------------------------------------
    164 
    165 class MessagePipeHandle : public Handle {
    166  public:
    167   MessagePipeHandle() {}
    168   explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
    169 
    170   // Copying and assignment allowed.
    171 };
    172 
    173 MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
    174                     bad_size_for_cpp_MessagePipeHandle);
    175 
    176 typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
    177 MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
    178                         sizeof(MessagePipeHandle),
    179                     bad_size_for_cpp_ScopedMessagePipeHandle);
    180 
    181 // TODO(vtl): In C++11, we could instead return a pair of
    182 // |ScopedHandleBase<MessagePipeHandle>|s.
    183 inline void CreateMessagePipe(ScopedMessagePipeHandle* message_pipe_0,
    184                               ScopedMessagePipeHandle* message_pipe_1) {
    185   assert(message_pipe_0);
    186   assert(message_pipe_1);
    187   MessagePipeHandle h_0;
    188   MessagePipeHandle h_1;
    189   MojoResult result MOJO_ALLOW_UNUSED =
    190       MojoCreateMessagePipe(h_0.mutable_value(), h_1.mutable_value());
    191   assert(result == MOJO_RESULT_OK);
    192   message_pipe_0->reset(h_0);
    193   message_pipe_1->reset(h_1);
    194 }
    195 
    196 // These "raw" versions fully expose the underlying API, but don't help with
    197 // ownership of handles (especially when writing messages).
    198 // TODO(vtl): Write "baked" versions.
    199 inline MojoResult WriteMessageRaw(
    200     MessagePipeHandle message_pipe,
    201     const void* bytes, uint32_t num_bytes,
    202     const MojoHandle* handles, uint32_t num_handles,
    203     MojoWriteMessageFlags flags) {
    204   return MojoWriteMessage(message_pipe.value(),
    205                           bytes, num_bytes,
    206                           handles, num_handles,
    207                           flags);
    208 }
    209 
    210 inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
    211                                  void* bytes, uint32_t* num_bytes,
    212                                  MojoHandle* handles, uint32_t* num_handles,
    213                                  MojoReadMessageFlags flags) {
    214   return MojoReadMessage(message_pipe.value(),
    215                          bytes, num_bytes,
    216                          handles, num_handles,
    217                          flags);
    218 }
    219 
    220 inline MojoTimeTicks GetTimeTicksNow() {
    221   return MojoGetTimeTicksNow();
    222 }
    223 
    224 }  // namespace mojo
    225 
    226 #endif  // MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
    227