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