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