1// Copyright 2014 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_HANDLE_H_ 6#define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ 7 8#include <assert.h> 9#include <limits> 10 11#include "mojo/public/c/system/functions.h" 12#include "mojo/public/c/system/types.h" 13#include "mojo/public/cpp/system/macros.h" 14 15namespace mojo { 16 17// OVERVIEW 18// 19// |Handle| and |...Handle|: 20// 21// |Handle| is a simple, copyable wrapper for the C type |MojoHandle| (which is 22// just an integer). Its purpose is to increase type-safety, not provide 23// lifetime management. For the same purpose, we have trivial *subclasses* of 24// |Handle|, e.g., |MessagePipeHandle| and |DataPipeProducerHandle|. |Handle| 25// and its subclasses impose *no* extra overhead over using |MojoHandle|s 26// directly. 27// 28// Note that though we provide constructors for |Handle|/|...Handle| from a 29// |MojoHandle|, we do not provide, e.g., a constructor for |MessagePipeHandle| 30// from a |Handle|. This is for type safety: If we did, you'd then be able to 31// construct a |MessagePipeHandle| from, e.g., a |DataPipeProducerHandle| (since 32// it's a |Handle|). 33// 34// |ScopedHandleBase| and |Scoped...Handle|: 35// 36// |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle 37// types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped 38// wrapper for a |T*|). It provides lifetime management, closing its owned 39// handle on destruction. It also provides (emulated) move semantics, again 40// along the lines of C++11's |unique_ptr| (and exactly like Chromium's 41// |scoped_ptr|). 42// 43// |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|. 44// Similarly, |ScopedMessagePipeHandle| is just a 45// |ScopedHandleBase<MessagePipeHandle>|. Etc. Note that a 46// |ScopedMessagePipeHandle| is *not* a (subclass of) |ScopedHandle|. 47// 48// Wrapper functions: 49// 50// We provide simple wrappers for the |Mojo...()| functions (in 51// mojo/public/c/system/core.h -- see that file for details on individual 52// functions). 53// 54// The general guideline is functions that imply ownership transfer of a handle 55// should take (or produce) an appropriate |Scoped...Handle|, while those that 56// don't take a |...Handle|. For example, |CreateMessagePipe()| has two 57// |ScopedMessagePipe| "out" parameters, whereas |Wait()| and |WaitMany()| take 58// |Handle| parameters. Some, have both: e.g., |DuplicatedBuffer()| takes a 59// suitable (unscoped) handle (e.g., |SharedBufferHandle|) "in" parameter and 60// produces a suitable scoped handle (e.g., |ScopedSharedBufferHandle| a.k.a. 61// |ScopedHandleBase<SharedBufferHandle>|) as an "out" parameter. 62// 63// An exception are some of the |...Raw()| functions. E.g., |CloseRaw()| takes a 64// |Handle|, leaving the user to discard the handle. 65// 66// More significantly, |WriteMessageRaw()| exposes the full API complexity of 67// |MojoWriteMessage()| (but doesn't require any extra overhead). It takes a raw 68// array of |Handle|s as input, and takes ownership of them (i.e., invalidates 69// them) on *success* (but not on failure). There are a number of reasons for 70// this. First, C++03 |std::vector|s cannot contain the move-only 71// |Scoped...Handle|s. Second, |std::vector|s impose extra overhead 72// (necessitating heap-allocation of the buffer). Third, |std::vector|s wouldn't 73// provide the desired level of flexibility/safety: a vector of handles would 74// have to be all of the same type (probably |Handle|/|ScopedHandle|). Fourth, 75// it's expected to not be used directly, but instead be used by generated 76// bindings. 77// 78// Other |...Raw()| functions expose similar rough edges, e.g., dealing with raw 79// pointers (and lengths) instead of taking |std::vector|s or similar. 80 81// ScopedHandleBase ------------------------------------------------------------ 82 83// Scoper for the actual handle types defined further below. It's move-only, 84// like the C++11 |unique_ptr|. 85template <class HandleType> 86class ScopedHandleBase { 87 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue) 88 89 public: 90 ScopedHandleBase() {} 91 explicit ScopedHandleBase(HandleType handle) : handle_(handle) {} 92 ~ScopedHandleBase() { CloseIfNecessary(); } 93 94 template <class CompatibleHandleType> 95 explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other) 96 : handle_(other.release()) { 97 } 98 99 // Move-only constructor and operator=. 100 ScopedHandleBase(RValue other) : handle_(other.object->release()) {} 101 ScopedHandleBase& operator=(RValue other) { 102 if (other.object != this) { 103 CloseIfNecessary(); 104 handle_ = other.object->release(); 105 } 106 return *this; 107 } 108 109 const HandleType& get() const { return handle_; } 110 111 template <typename PassedHandleType> 112 static ScopedHandleBase<HandleType> From( 113 ScopedHandleBase<PassedHandleType> other) { 114 MOJO_COMPILE_ASSERT( 115 sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))), 116 HandleType_is_not_a_subtype_of_PassedHandleType); 117 return ScopedHandleBase<HandleType>( 118 static_cast<HandleType>(other.release().value())); 119 } 120 121 void swap(ScopedHandleBase& other) { 122 handle_.swap(other.handle_); 123 } 124 125 HandleType release() MOJO_WARN_UNUSED_RESULT { 126 HandleType rv; 127 rv.swap(handle_); 128 return rv; 129 } 130 131 void reset(HandleType handle = HandleType()) { 132 CloseIfNecessary(); 133 handle_ = handle; 134 } 135 136 bool is_valid() const { 137 return handle_.is_valid(); 138 } 139 140 private: 141 void CloseIfNecessary() { 142 if (!handle_.is_valid()) 143 return; 144 MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value()); 145 assert(result == MOJO_RESULT_OK); 146 } 147 148 HandleType handle_; 149}; 150 151template <typename HandleType> 152inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) { 153 return ScopedHandleBase<HandleType>(handle); 154} 155 156// Handle ---------------------------------------------------------------------- 157 158const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID; 159 160// Wrapper base class for |MojoHandle|. 161class Handle { 162 public: 163 Handle() : value_(kInvalidHandleValue) {} 164 explicit Handle(MojoHandle value) : value_(value) {} 165 ~Handle() {} 166 167 void swap(Handle& other) { 168 MojoHandle temp = value_; 169 value_ = other.value_; 170 other.value_ = temp; 171 } 172 173 bool is_valid() const { 174 return value_ != kInvalidHandleValue; 175 } 176 177 const MojoHandle& value() const { return value_; } 178 MojoHandle* mutable_value() { return &value_; } 179 void set_value(MojoHandle value) { value_ = value; } 180 181 private: 182 MojoHandle value_; 183 184 // Copying and assignment allowed. 185}; 186 187// Should have zero overhead. 188MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle), 189 bad_size_for_cpp_Handle); 190 191// The scoper should also impose no more overhead. 192typedef ScopedHandleBase<Handle> ScopedHandle; 193MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle), 194 bad_size_for_cpp_ScopedHandle); 195 196inline MojoResult Wait(Handle handle, 197 MojoHandleSignals signals, 198 MojoDeadline deadline) { 199 return MojoWait(handle.value(), signals, deadline); 200} 201 202// |HandleVectorType| and |FlagsVectorType| should be similar enough to 203// |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively: 204// - They should have a (const) |size()| method that returns an unsigned type. 205// - They must provide contiguous storage, with access via (const) reference to 206// that storage provided by a (const) |operator[]()| (by reference). 207template <class HandleVectorType, class FlagsVectorType> 208inline MojoResult WaitMany(const HandleVectorType& handles, 209 const FlagsVectorType& signals, 210 MojoDeadline deadline) { 211 if (signals.size() != handles.size()) 212 return MOJO_RESULT_INVALID_ARGUMENT; 213 if (handles.size() > std::numeric_limits<uint32_t>::max()) 214 return MOJO_RESULT_OUT_OF_RANGE; 215 216 if (handles.size() == 0) 217 return MojoWaitMany(NULL, NULL, 0, deadline); 218 219 const Handle& first_handle = handles[0]; 220 const MojoHandleSignals& first_signals = signals[0]; 221 return MojoWaitMany( 222 reinterpret_cast<const MojoHandle*>(&first_handle), 223 reinterpret_cast<const MojoHandleSignals*>(&first_signals), 224 static_cast<uint32_t>(handles.size()), 225 deadline); 226} 227 228// |Close()| takes ownership of the handle, since it'll invalidate it. 229// Note: There's nothing to do, since the argument will be destroyed when it 230// goes out of scope. 231template <class HandleType> 232inline void Close(ScopedHandleBase<HandleType> /*handle*/) {} 233 234// Most users should typically use |Close()| (above) instead. 235inline MojoResult CloseRaw(Handle handle) { 236 return MojoClose(handle.value()); 237} 238 239// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, 240inline bool operator<(const Handle a, const Handle b) { 241 return a.value() < b.value(); 242} 243 244} // namespace mojo 245 246#endif // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ 247