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