| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ | 5 #ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ |
| 6 #define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ | 6 #define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ |
| 7 | 7 |
| 8 #include <assert.h> | 8 #include "mojo/public/cpp/system/buffer.h" |
| 9 #include <stddef.h> | 9 #include "mojo/public/cpp/system/data_pipe.h" |
| 10 | 10 #include "mojo/public/cpp/system/functions.h" |
| 11 #include <limits> | 11 #include "mojo/public/cpp/system/handle.h" |
| 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" | 12 #include "mojo/public/cpp/system/macros.h" |
| 16 | 13 #include "mojo/public/cpp/system/message_pipe.h" |
| 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 | 14 |
| 555 #endif // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ | 15 #endif // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_ |
| OLD | NEW |