| OLD | NEW |
| (Empty) |
| 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 #include <stddef.h> | |
| 10 | |
| 11 #include <limits> | |
| 12 | |
| 13 #include "mojo/public/c/system/core.h" | |
| 14 #include "mojo/public/c/system/macros.h" | |
| 15 #include "mojo/public/c/system/system_export.h" | |
| 16 | |
| 17 namespace mojo { | |
| 18 | |
| 19 // Standalone functions -------------------------------------------------------- | |
| 20 | |
| 21 inline MojoTimeTicks GetTimeTicksNow() { | |
| 22 return MojoGetTimeTicksNow(); | |
| 23 } | |
| 24 | |
| 25 // ScopedHandleBase ------------------------------------------------------------ | |
| 26 | |
| 27 // Scoper for the actual handle types defined further below. It's move-only, | |
| 28 // like the C++11 |unique_ptr|. | |
| 29 template <class HandleType> | |
| 30 class ScopedHandleBase { | |
| 31 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue) | |
| 32 | |
| 33 public: | |
| 34 ScopedHandleBase() {} | |
| 35 explicit ScopedHandleBase(HandleType handle) : handle_(handle) {} | |
| 36 ~ScopedHandleBase() { CloseIfNecessary(); } | |
| 37 | |
| 38 template <class CompatibleHandleType> | |
| 39 explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other) | |
| 40 : handle_(other.release()) { | |
| 41 } | |
| 42 | |
| 43 // Move-only constructor and operator=. | |
| 44 ScopedHandleBase(RValue other) : handle_(other.object->release()) {} | |
| 45 ScopedHandleBase& operator=(RValue other) { | |
| 46 handle_ = other.object->release(); | |
| 47 return *this; | |
| 48 } | |
| 49 | |
| 50 const HandleType& get() const { return handle_; } | |
| 51 | |
| 52 void swap(ScopedHandleBase& other) { | |
| 53 handle_.swap(other.handle_); | |
| 54 } | |
| 55 | |
| 56 HandleType release() MOJO_WARN_UNUSED_RESULT { | |
| 57 HandleType rv; | |
| 58 rv.swap(handle_); | |
| 59 return rv; | |
| 60 } | |
| 61 | |
| 62 void reset(HandleType handle = HandleType()) { | |
| 63 CloseIfNecessary(); | |
| 64 handle_ = handle; | |
| 65 } | |
| 66 | |
| 67 bool is_valid() const { | |
| 68 return handle_.is_valid(); | |
| 69 } | |
| 70 | |
| 71 private: | |
| 72 void CloseIfNecessary() { | |
| 73 if (!handle_.is_valid()) | |
| 74 return; | |
| 75 MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value()); | |
| 76 assert(result == MOJO_RESULT_OK); | |
| 77 } | |
| 78 | |
| 79 HandleType handle_; | |
| 80 }; | |
| 81 | |
| 82 template <typename HandleType> | |
| 83 inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) { | |
| 84 return ScopedHandleBase<HandleType>(handle); | |
| 85 } | |
| 86 | |
| 87 // Handle ---------------------------------------------------------------------- | |
| 88 | |
| 89 const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID; | |
| 90 | |
| 91 // Wrapper base class for |MojoHandle|. | |
| 92 class Handle { | |
| 93 public: | |
| 94 Handle() : value_(MOJO_HANDLE_INVALID) {} | |
| 95 explicit Handle(MojoHandle value) : value_(value) {} | |
| 96 ~Handle() {} | |
| 97 | |
| 98 void swap(Handle& other) { | |
| 99 MojoHandle temp = value_; | |
| 100 value_ = other.value_; | |
| 101 other.value_ = temp; | |
| 102 } | |
| 103 | |
| 104 bool is_valid() const { | |
| 105 return value_ != MOJO_HANDLE_INVALID; | |
| 106 } | |
| 107 | |
| 108 MojoHandle value() const { return value_; } | |
| 109 MojoHandle* mutable_value() { return &value_; } | |
| 110 void set_value(MojoHandle value) { value_ = value; } | |
| 111 | |
| 112 private: | |
| 113 MojoHandle value_; | |
| 114 | |
| 115 // Copying and assignment allowed. | |
| 116 }; | |
| 117 | |
| 118 // Should have zero overhead. | |
| 119 MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle), | |
| 120 bad_size_for_cpp_Handle); | |
| 121 | |
| 122 // The scoper should also impose no more overhead. | |
| 123 typedef ScopedHandleBase<Handle> ScopedHandle; | |
| 124 MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle), | |
| 125 bad_size_for_cpp_ScopedHandle); | |
| 126 | |
| 127 inline MojoResult Wait(const Handle& handle, | |
| 128 MojoWaitFlags flags, | |
| 129 MojoDeadline deadline) { | |
| 130 return MojoWait(handle.value(), flags, deadline); | |
| 131 } | |
| 132 | |
| 133 // |HandleVectorType| and |FlagsVectorType| should be similar enough to | |
| 134 // |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively: | |
| 135 // - They should have a (const) |size()| method that returns an unsigned type. | |
| 136 // - They must provide contiguous storage, with access via (const) reference to | |
| 137 // that storage provided by a (const) |operator[]()| (by reference). | |
| 138 template <class HandleVectorType, class FlagsVectorType> | |
| 139 inline MojoResult WaitMany(const HandleVectorType& handles, | |
| 140 const FlagsVectorType& flags, | |
| 141 MojoDeadline deadline) { | |
| 142 if (flags.size() != handles.size()) | |
| 143 return MOJO_RESULT_INVALID_ARGUMENT; | |
| 144 if (handles.size() > std::numeric_limits<uint32_t>::max()) | |
| 145 return MOJO_RESULT_OUT_OF_RANGE; | |
| 146 | |
| 147 if (handles.size() == 0) | |
| 148 return MojoWaitMany(NULL, NULL, 0, deadline); | |
| 149 | |
| 150 const Handle& first_handle = handles[0]; | |
| 151 const MojoWaitFlags& first_flag = flags[0]; | |
| 152 return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle), | |
| 153 reinterpret_cast<const MojoWaitFlags*>(&first_flag), | |
| 154 static_cast<uint32_t>(handles.size()), | |
| 155 deadline); | |
| 156 } | |
| 157 | |
| 158 // |Close()| takes ownership of the handle, since it'll invalidate it. | |
| 159 // Note: There's nothing to do, since the argument will be destroyed when it | |
| 160 // goes out of scope. | |
| 161 template <class HandleType> | |
| 162 inline void Close(ScopedHandleBase<HandleType> /*handle*/) {} | |
| 163 | |
| 164 // Most users should typically use |Close()| (above) instead. | |
| 165 inline MojoResult CloseRaw(Handle handle) { | |
| 166 return MojoClose(handle.value()); | |
| 167 } | |
| 168 | |
| 169 // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, | |
| 170 // etc. | |
| 171 inline bool operator<(const Handle& a, const Handle& b) { | |
| 172 return a.value() < b.value(); | |
| 173 } | |
| 174 | |
| 175 // MessagePipeHandle ----------------------------------------------------------- | |
| 176 | |
| 177 class MessagePipeHandle : public Handle { | |
| 178 public: | |
| 179 MessagePipeHandle() {} | |
| 180 explicit MessagePipeHandle(MojoHandle value) : Handle(value) {} | |
| 181 | |
| 182 // Copying and assignment allowed. | |
| 183 }; | |
| 184 | |
| 185 MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle), | |
| 186 bad_size_for_cpp_MessagePipeHandle); | |
| 187 | |
| 188 typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle; | |
| 189 MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) == | |
| 190 sizeof(MessagePipeHandle), | |
| 191 bad_size_for_cpp_ScopedMessagePipeHandle); | |
| 192 | |
| 193 inline MojoResult CreateMessagePipe(ScopedMessagePipeHandle* message_pipe0, | |
| 194 ScopedMessagePipeHandle* message_pipe1) { | |
| 195 assert(message_pipe0); | |
| 196 assert(message_pipe1); | |
| 197 MessagePipeHandle handle0; | |
| 198 MessagePipeHandle handle1; | |
| 199 MojoResult rv = MojoCreateMessagePipe(handle0.mutable_value(), | |
| 200 handle1.mutable_value()); | |
| 201 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
| 202 // will be used). | |
| 203 message_pipe0->reset(handle0); | |
| 204 message_pipe1->reset(handle1); | |
| 205 return rv; | |
| 206 } | |
| 207 | |
| 208 // These "raw" versions fully expose the underlying API, but don't help with | |
| 209 // ownership of handles (especially when writing messages). | |
| 210 // TODO(vtl): Write "baked" versions. | |
| 211 inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe, | |
| 212 const void* bytes, | |
| 213 uint32_t num_bytes, | |
| 214 const MojoHandle* handles, | |
| 215 uint32_t num_handles, | |
| 216 MojoWriteMessageFlags flags) { | |
| 217 return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles, | |
| 218 num_handles, flags); | |
| 219 } | |
| 220 | |
| 221 inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, | |
| 222 void* bytes, | |
| 223 uint32_t* num_bytes, | |
| 224 MojoHandle* handles, | |
| 225 uint32_t* num_handles, | |
| 226 MojoReadMessageFlags flags) { | |
| 227 return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles, | |
| 228 num_handles, flags); | |
| 229 } | |
| 230 | |
| 231 // A wrapper class that automatically creates a message pipe and owns both | |
| 232 // handles. | |
| 233 class MessagePipe { | |
| 234 public: | |
| 235 MessagePipe(); | |
| 236 ~MessagePipe(); | |
| 237 | |
| 238 ScopedMessagePipeHandle handle0; | |
| 239 ScopedMessagePipeHandle handle1; | |
| 240 }; | |
| 241 | |
| 242 inline MessagePipe::MessagePipe() { | |
| 243 MojoResult result MOJO_ALLOW_UNUSED = CreateMessagePipe(&handle0, &handle1); | |
| 244 assert(result == MOJO_RESULT_OK); | |
| 245 } | |
| 246 | |
| 247 inline MessagePipe::~MessagePipe() { | |
| 248 } | |
| 249 | |
| 250 // DataPipeProducerHandle and DataPipeConsumerHandle --------------------------- | |
| 251 | |
| 252 class DataPipeProducerHandle : public Handle { | |
| 253 public: | |
| 254 DataPipeProducerHandle() {} | |
| 255 explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {} | |
| 256 | |
| 257 // Copying and assignment allowed. | |
| 258 }; | |
| 259 | |
| 260 MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle), | |
| 261 bad_size_for_cpp_DataPipeProducerHandle); | |
| 262 | |
| 263 typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle; | |
| 264 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) == | |
| 265 sizeof(DataPipeProducerHandle), | |
| 266 bad_size_for_cpp_ScopedDataPipeProducerHandle); | |
| 267 | |
| 268 class DataPipeConsumerHandle : public Handle { | |
| 269 public: | |
| 270 DataPipeConsumerHandle() {} | |
| 271 explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {} | |
| 272 | |
| 273 // Copying and assignment allowed. | |
| 274 }; | |
| 275 | |
| 276 MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle), | |
| 277 bad_size_for_cpp_DataPipeConsumerHandle); | |
| 278 | |
| 279 typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle; | |
| 280 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) == | |
| 281 sizeof(DataPipeConsumerHandle), | |
| 282 bad_size_for_cpp_ScopedDataPipeConsumerHandle); | |
| 283 | |
| 284 inline MojoResult CreateDataPipe( | |
| 285 const MojoCreateDataPipeOptions* options, | |
| 286 ScopedDataPipeProducerHandle* data_pipe_producer, | |
| 287 ScopedDataPipeConsumerHandle* data_pipe_consumer) { | |
| 288 assert(data_pipe_producer); | |
| 289 assert(data_pipe_consumer); | |
| 290 DataPipeProducerHandle producer_handle; | |
| 291 DataPipeConsumerHandle consumer_handle; | |
| 292 MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(), | |
| 293 consumer_handle.mutable_value()); | |
| 294 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
| 295 // will be used). | |
| 296 data_pipe_producer->reset(producer_handle); | |
| 297 data_pipe_consumer->reset(consumer_handle); | |
| 298 return rv; | |
| 299 } | |
| 300 | |
| 301 inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
| 302 const void* elements, | |
| 303 uint32_t* num_bytes, | |
| 304 MojoWriteDataFlags flags) { | |
| 305 return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags); | |
| 306 } | |
| 307 | |
| 308 inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
| 309 void** buffer, | |
| 310 uint32_t* buffer_num_bytes, | |
| 311 MojoWriteDataFlags flags) { | |
| 312 return MojoBeginWriteData(data_pipe_producer.value(), buffer, | |
| 313 buffer_num_bytes, flags); | |
| 314 } | |
| 315 | |
| 316 inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
| 317 uint32_t num_bytes_written) { | |
| 318 return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written); | |
| 319 } | |
| 320 | |
| 321 inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
| 322 void* elements, | |
| 323 uint32_t* num_bytes, | |
| 324 MojoReadDataFlags flags) { | |
| 325 return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags); | |
| 326 } | |
| 327 | |
| 328 inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
| 329 const void** buffer, | |
| 330 uint32_t* buffer_num_bytes, | |
| 331 MojoReadDataFlags flags) { | |
| 332 return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes, | |
| 333 flags); | |
| 334 } | |
| 335 | |
| 336 inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
| 337 uint32_t num_bytes_read) { | |
| 338 return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read); | |
| 339 } | |
| 340 | |
| 341 // A wrapper class that automatically creates a data pipe and owns both handles. | |
| 342 // TODO(vtl): Make an even more friendly version? (Maybe templatized for a | |
| 343 // particular type instead of some "element"? Maybe functions that take | |
| 344 // vectors?) | |
| 345 class DataPipe { | |
| 346 public: | |
| 347 DataPipe(); | |
| 348 explicit DataPipe(const MojoCreateDataPipeOptions& options); | |
| 349 ~DataPipe(); | |
| 350 | |
| 351 ScopedDataPipeProducerHandle producer_handle; | |
| 352 ScopedDataPipeConsumerHandle consumer_handle; | |
| 353 }; | |
| 354 | |
| 355 inline DataPipe::DataPipe() { | |
| 356 MojoResult result MOJO_ALLOW_UNUSED = | |
| 357 CreateDataPipe(NULL, &producer_handle, &consumer_handle); | |
| 358 assert(result == MOJO_RESULT_OK); | |
| 359 } | |
| 360 | |
| 361 inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) { | |
| 362 MojoResult result MOJO_ALLOW_UNUSED = | |
| 363 CreateDataPipe(&options, &producer_handle, &consumer_handle); | |
| 364 assert(result == MOJO_RESULT_OK); | |
| 365 } | |
| 366 | |
| 367 inline DataPipe::~DataPipe() { | |
| 368 } | |
| 369 | |
| 370 // SharedBufferHandle ---------------------------------------------------------- | |
| 371 | |
| 372 class SharedBufferHandle : public Handle { | |
| 373 public: | |
| 374 SharedBufferHandle() {} | |
| 375 explicit SharedBufferHandle(MojoHandle value) : Handle(value) {} | |
| 376 | |
| 377 // Copying and assignment allowed. | |
| 378 }; | |
| 379 | |
| 380 MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle), | |
| 381 bad_size_for_cpp_SharedBufferHandle); | |
| 382 | |
| 383 typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle; | |
| 384 MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) == | |
| 385 sizeof(SharedBufferHandle), | |
| 386 bad_size_for_cpp_ScopedSharedBufferHandle); | |
| 387 | |
| 388 inline MojoResult CreateSharedBuffer( | |
| 389 const MojoCreateSharedBufferOptions* options, | |
| 390 uint64_t num_bytes, | |
| 391 ScopedSharedBufferHandle* shared_buffer) { | |
| 392 assert(shared_buffer); | |
| 393 SharedBufferHandle handle; | |
| 394 MojoResult rv = MojoCreateSharedBuffer(options, num_bytes, | |
| 395 handle.mutable_value()); | |
| 396 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
| 397 // will be used). | |
| 398 shared_buffer->reset(handle); | |
| 399 return rv; | |
| 400 } | |
| 401 | |
| 402 // TODO(vtl): This (and also the functions below) are templatized to allow for | |
| 403 // future/other buffer types. A bit "safer" would be to overload this function | |
| 404 // manually. (The template enforces that the in and out handles to be of the | |
| 405 // same type.) | |
| 406 template <class BufferHandleType> | |
| 407 inline MojoResult DuplicatedBuffer( | |
| 408 BufferHandleType buffer, | |
| 409 const MojoDuplicateBufferHandleOptions* options, | |
| 410 ScopedHandleBase<BufferHandleType>* new_buffer) { | |
| 411 assert(new_buffer); | |
| 412 BufferHandleType handle; | |
| 413 MojoResult rv = MojoDuplicateSharedBuffer(buffer.value(), options, | |
| 414 handle.mutable_value()); | |
| 415 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
| 416 // will be used). | |
| 417 new_buffer->reset(handle); | |
| 418 return rv; | |
| 419 } | |
| 420 | |
| 421 template <class BufferHandleType> | |
| 422 inline MojoResult MapBuffer(BufferHandleType buffer, | |
| 423 uint64_t offset, | |
| 424 uint64_t num_bytes, | |
| 425 void** pointer, | |
| 426 MojoMapBufferFlags flags) { | |
| 427 assert(buffer); | |
| 428 return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags); | |
| 429 } | |
| 430 | |
| 431 inline MojoResult UnmapBuffer(void* pointer) { | |
| 432 assert(pointer); | |
| 433 return MojoUnmapBuffer(pointer); | |
| 434 } | |
| 435 | |
| 436 // A wrapper class that automatically creates a shared buffer and owns the | |
| 437 // handle. | |
| 438 class SharedBuffer { | |
| 439 public: | |
| 440 explicit SharedBuffer(uint64_t num_bytes); | |
| 441 SharedBuffer(uint64_t num_bytes, | |
| 442 const MojoCreateSharedBufferOptions& options); | |
| 443 ~SharedBuffer(); | |
| 444 | |
| 445 ScopedSharedBufferHandle handle; | |
| 446 }; | |
| 447 | |
| 448 inline SharedBuffer::SharedBuffer(uint64_t num_bytes) { | |
| 449 MojoResult result MOJO_ALLOW_UNUSED = | |
| 450 CreateSharedBuffer(NULL, num_bytes, &handle); | |
| 451 assert(result == MOJO_RESULT_OK); | |
| 452 } | |
| 453 | |
| 454 inline SharedBuffer::SharedBuffer( | |
| 455 uint64_t num_bytes, | |
| 456 const MojoCreateSharedBufferOptions& options) { | |
| 457 MojoResult result MOJO_ALLOW_UNUSED = | |
| 458 CreateSharedBuffer(&options, num_bytes, &handle); | |
| 459 assert(result == MOJO_RESULT_OK); | |
| 460 } | |
| 461 | |
| 462 inline SharedBuffer::~SharedBuffer() { | |
| 463 } | |
| 464 | |
| 465 } // namespace mojo | |
| 466 | |
| 467 #endif // MOJO_PUBLIC_SYSTEM_CORE_CPP_H_ | |
| OLD | NEW |