| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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_HANDLE_H_ | 5 #ifndef MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ |
| 6 #define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ | 6 #define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ |
| 7 | 7 |
| 8 #include <assert.h> | 8 #include <assert.h> |
| 9 #include <limits> | 9 #include <limits> |
| 10 | 10 |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 }; | 179 }; |
| 180 | 180 |
| 181 // Should have zero overhead. | 181 // Should have zero overhead. |
| 182 static_assert(sizeof(Handle) == sizeof(MojoHandle), "Bad size for C++ Handle"); | 182 static_assert(sizeof(Handle) == sizeof(MojoHandle), "Bad size for C++ Handle"); |
| 183 | 183 |
| 184 // The scoper should also impose no more overhead. | 184 // The scoper should also impose no more overhead. |
| 185 typedef ScopedHandleBase<Handle> ScopedHandle; | 185 typedef ScopedHandleBase<Handle> ScopedHandle; |
| 186 static_assert(sizeof(ScopedHandle) == sizeof(Handle), | 186 static_assert(sizeof(ScopedHandle) == sizeof(Handle), |
| 187 "Bad size for C++ ScopedHandle"); | 187 "Bad size for C++ ScopedHandle"); |
| 188 | 188 |
| 189 // TODO(jimbe): Remove this function |
| 189 inline MojoResult Wait(Handle handle, | 190 inline MojoResult Wait(Handle handle, |
| 190 MojoHandleSignals signals, | 191 MojoHandleSignals signals, |
| 191 MojoDeadline deadline) { | 192 MojoDeadline deadline) { |
| 192 return MojoWait(handle.value(), signals, deadline); | 193 return MojoWait(handle.value(), signals, deadline); |
| 193 } | 194 } |
| 194 | 195 |
| 196 inline MojoResult Wait(Handle handle, |
| 197 MojoHandleSignals signals, |
| 198 MojoDeadline deadline, |
| 199 MojoHandleSignalsState* signals_state) { |
| 200 return MojoNewWait(handle.value(), signals, deadline, signals_state); |
| 201 } |
| 202 |
| 203 // TODO(jimbe): Remove this function |
| 195 // |HandleVectorType| and |FlagsVectorType| should be similar enough to | 204 // |HandleVectorType| and |FlagsVectorType| should be similar enough to |
| 196 // |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively: | 205 // |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively: |
| 197 // - They should have a (const) |size()| method that returns an unsigned type. | 206 // - They should have a (const) |size()| method that returns an unsigned type. |
| 198 // - They must provide contiguous storage, with access via (const) reference to | 207 // - They must provide contiguous storage, with access via (const) reference to |
| 199 // that storage provided by a (const) |operator[]()| (by reference). | 208 // that storage provided by a (const) |operator[]()| (by reference). |
| 200 template <class HandleVectorType, class FlagsVectorType> | 209 template <class HandleVectorType, class FlagsVectorType> |
| 201 inline MojoResult WaitMany(const HandleVectorType& handles, | 210 inline MojoResult WaitMany(const HandleVectorType& handles, |
| 202 const FlagsVectorType& signals, | 211 const FlagsVectorType& signals, |
| 203 MojoDeadline deadline) { | 212 MojoDeadline deadline) { |
| 204 if (signals.size() != handles.size()) | 213 if (signals.size() != handles.size()) |
| 205 return MOJO_RESULT_INVALID_ARGUMENT; | 214 return MOJO_RESULT_INVALID_ARGUMENT; |
| 206 if (handles.size() > std::numeric_limits<uint32_t>::max()) | 215 if (handles.size() > std::numeric_limits<uint32_t>::max()) |
| 207 return MOJO_RESULT_OUT_OF_RANGE; | 216 return MOJO_RESULT_OUT_OF_RANGE; |
| 208 | 217 |
| 209 if (handles.size() == 0) | 218 if (handles.size() == 0) |
| 210 return MojoWaitMany(nullptr, nullptr, 0, deadline); | 219 return MojoWaitMany(nullptr, nullptr, 0, deadline); |
| 211 | 220 |
| 212 const Handle& first_handle = handles[0]; | 221 const Handle& first_handle = handles[0]; |
| 213 const MojoHandleSignals& first_signals = signals[0]; | 222 const MojoHandleSignals& first_signals = signals[0]; |
| 214 return MojoWaitMany( | 223 return MojoWaitMany( |
| 215 reinterpret_cast<const MojoHandle*>(&first_handle), | 224 reinterpret_cast<const MojoHandle*>(&first_handle), |
| 216 reinterpret_cast<const MojoHandleSignals*>(&first_signals), | 225 reinterpret_cast<const MojoHandleSignals*>(&first_signals), |
| 217 static_cast<uint32_t>(handles.size()), | 226 static_cast<uint32_t>(handles.size()), |
| 218 deadline); | 227 deadline); |
| 219 } | 228 } |
| 220 | 229 |
| 230 const uint32_t kInvalidWaitManyIndexValue = static_cast<uint32_t>(-1); |
| 231 |
| 232 // Simplify the interpretation of the output from |MojoWaitMany()|. |
| 233 class WaitManyResult { |
| 234 public: |
| 235 explicit WaitManyResult(MojoResult mojo_wait_many_result) |
| 236 : result(mojo_wait_many_result), index(kInvalidWaitManyIndexValue) {} |
| 237 |
| 238 WaitManyResult(MojoResult mojo_wait_many_result, uint32_t result_index) |
| 239 : result(mojo_wait_many_result), index(result_index) {} |
| 240 |
| 241 // A valid handle index is always returned if |WaitMany()| succeeds, but may |
| 242 // or may not be returned if |WaitMany()| returns an error. Use this helper |
| 243 // function to check if |index| is a valid index into the handle array. |
| 244 bool IsIndexValid() const { return index != kInvalidWaitManyIndexValue; } |
| 245 |
| 246 // The |signals_states| array is always returned by |WaitMany()| on success, |
| 247 // but may or may not be returned if |WaitMany()| returns an error. Use this |
| 248 // helper function to check if |signals_states| holds valid data. |
| 249 bool AreSignalsStatesValid() const { |
| 250 return result != MOJO_RESULT_INVALID_ARGUMENT && |
| 251 result != MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 252 } |
| 253 |
| 254 MojoResult result; |
| 255 uint32_t index; |
| 256 }; |
| 257 |
| 258 // |HandleVectorType| and |FlagsVectorType| should be similar enough to |
| 259 // |std::vector<Handle>| and |std::vector<MojoHandleSignals>|, respectively: |
| 260 // - They should have a (const) |size()| method that returns an unsigned type. |
| 261 // - They must provide contiguous storage, with access via (const) reference to |
| 262 // that storage provided by a (const) |operator[]()| (by reference). |
| 263 template <class HandleVectorType, |
| 264 class FlagsVectorType, |
| 265 class SignalsStateVectorType> |
| 266 inline WaitManyResult WaitMany(const HandleVectorType& handles, |
| 267 const FlagsVectorType& signals, |
| 268 MojoDeadline deadline, |
| 269 SignalsStateVectorType* signals_states) { |
| 270 if (signals.size() != handles.size() || |
| 271 (signals_states && signals_states->size() != signals.size())) |
| 272 return WaitManyResult(MOJO_RESULT_INVALID_ARGUMENT); |
| 273 if (handles.size() >= kInvalidWaitManyIndexValue) |
| 274 return WaitManyResult(MOJO_RESULT_RESOURCE_EXHAUSTED); |
| 275 |
| 276 if (handles.size() == 0) { |
| 277 return WaitManyResult( |
| 278 MojoNewWaitMany(nullptr, nullptr, 0, deadline, nullptr, nullptr)); |
| 279 } |
| 280 |
| 281 uint32_t result_index = kInvalidWaitManyIndexValue; |
| 282 const Handle& first_handle = handles[0]; |
| 283 const MojoHandleSignals& first_signals = signals[0]; |
| 284 MojoHandleSignalsState* first_state = |
| 285 signals_states ? &(*signals_states)[0] : nullptr; |
| 286 MojoResult result = |
| 287 MojoNewWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle), |
| 288 &first_signals, static_cast<uint32_t>(handles.size()), |
| 289 deadline, &result_index, first_state); |
| 290 return WaitManyResult(result, result_index); |
| 291 } |
| 292 |
| 293 // C++ 4.10, regarding pointer conversion, says that an integral null pointer |
| 294 // constant can be converted to |std::nullptr_t| (which is a typedef for |
| 295 // |decltype(nullptr)|). The opposite direction is not allowed. |
| 296 template <class HandleVectorType, class FlagsVectorType> |
| 297 inline WaitManyResult WaitMany(const HandleVectorType& handles, |
| 298 const FlagsVectorType& signals, |
| 299 MojoDeadline deadline, |
| 300 decltype(nullptr) signals_states) { |
| 301 if (signals.size() != handles.size()) |
| 302 return WaitManyResult(MOJO_RESULT_INVALID_ARGUMENT); |
| 303 if (handles.size() >= kInvalidWaitManyIndexValue) |
| 304 return WaitManyResult(MOJO_RESULT_OUT_OF_RANGE); |
| 305 |
| 306 if (handles.size() == 0) { |
| 307 return WaitManyResult( |
| 308 MojoNewWaitMany(nullptr, nullptr, 0, deadline, nullptr, nullptr)); |
| 309 } |
| 310 |
| 311 uint32_t result_index = kInvalidWaitManyIndexValue; |
| 312 const Handle& first_handle = handles[0]; |
| 313 const MojoHandleSignals& first_signals = signals[0]; |
| 314 MojoResult result = MojoNewWaitMany( |
| 315 reinterpret_cast<const MojoHandle*>(&first_handle), &first_signals, |
| 316 static_cast<uint32_t>(handles.size()), deadline, &result_index, nullptr); |
| 317 return WaitManyResult(result, result_index); |
| 318 } |
| 319 |
| 221 // |Close()| takes ownership of the handle, since it'll invalidate it. | 320 // |Close()| takes ownership of the handle, since it'll invalidate it. |
| 222 // Note: There's nothing to do, since the argument will be destroyed when it | 321 // Note: There's nothing to do, since the argument will be destroyed when it |
| 223 // goes out of scope. | 322 // goes out of scope. |
| 224 template <class HandleType> | 323 template <class HandleType> |
| 225 inline void Close(ScopedHandleBase<HandleType> /*handle*/) { | 324 inline void Close(ScopedHandleBase<HandleType> /*handle*/) { |
| 226 } | 325 } |
| 227 | 326 |
| 228 // Most users should typically use |Close()| (above) instead. | 327 // Most users should typically use |Close()| (above) instead. |
| 229 inline MojoResult CloseRaw(Handle handle) { | 328 inline MojoResult CloseRaw(Handle handle) { |
| 230 return MojoClose(handle.value()); | 329 return MojoClose(handle.value()); |
| 231 } | 330 } |
| 232 | 331 |
| 233 // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, | 332 // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, |
| 234 inline bool operator<(const Handle a, const Handle b) { | 333 inline bool operator<(const Handle a, const Handle b) { |
| 235 return a.value() < b.value(); | 334 return a.value() < b.value(); |
| 236 } | 335 } |
| 237 | 336 |
| 238 } // namespace mojo | 337 } // namespace mojo |
| 239 | 338 |
| 240 #endif // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ | 339 #endif // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_ |
| OLD | NEW |