OLD | NEW |
| (Empty) |
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_SYSTEM_CORE_CPP_H_ | |
6 #define MOJO_PUBLIC_SYSTEM_CORE_CPP_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/macros.h" | |
15 #include "mojo/public/c/system/system_export.h" | |
16 | |
17 namespace mojo { | |
18 | |
19 // Standalone functions -------------------------------------------------------- | |
20 | |
21 inline MojoTimeTicks GetTimeTicksNow() { | |
22 return MojoGetTimeTicksNow(); | |
23 } | |
24 | |
25 // ScopedHandleBase ------------------------------------------------------------ | |
26 | |
27 // Scoper for the actual handle types defined further below. It's move-only, | |
28 // like the C++11 |unique_ptr|. | |
29 template <class HandleType> | |
30 class ScopedHandleBase { | |
31 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue) | |
32 | |
33 public: | |
34 ScopedHandleBase() {} | |
35 explicit ScopedHandleBase(HandleType handle) : handle_(handle) {} | |
36 ~ScopedHandleBase() { CloseIfNecessary(); } | |
37 | |
38 template <class CompatibleHandleType> | |
39 explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other) | |
40 : handle_(other.release()) { | |
41 } | |
42 | |
43 // Move-only constructor and operator=. | |
44 ScopedHandleBase(RValue other) : handle_(other.object->release()) {} | |
45 ScopedHandleBase& operator=(RValue other) { | |
46 handle_ = other.object->release(); | |
47 return *this; | |
48 } | |
49 | |
50 const HandleType& get() const { return handle_; } | |
51 | |
52 void swap(ScopedHandleBase& other) { | |
53 handle_.swap(other.handle_); | |
54 } | |
55 | |
56 HandleType release() MOJO_WARN_UNUSED_RESULT { | |
57 HandleType rv; | |
58 rv.swap(handle_); | |
59 return rv; | |
60 } | |
61 | |
62 void reset(HandleType handle = HandleType()) { | |
63 CloseIfNecessary(); | |
64 handle_ = handle; | |
65 } | |
66 | |
67 bool is_valid() const { | |
68 return handle_.is_valid(); | |
69 } | |
70 | |
71 private: | |
72 void CloseIfNecessary() { | |
73 if (!handle_.is_valid()) | |
74 return; | |
75 MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value()); | |
76 assert(result == MOJO_RESULT_OK); | |
77 } | |
78 | |
79 HandleType handle_; | |
80 }; | |
81 | |
82 template <typename HandleType> | |
83 inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) { | |
84 return ScopedHandleBase<HandleType>(handle); | |
85 } | |
86 | |
87 // Handle ---------------------------------------------------------------------- | |
88 | |
89 const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID; | |
90 | |
91 // Wrapper base class for |MojoHandle|. | |
92 class Handle { | |
93 public: | |
94 Handle() : value_(MOJO_HANDLE_INVALID) {} | |
95 explicit Handle(MojoHandle value) : value_(value) {} | |
96 ~Handle() {} | |
97 | |
98 void swap(Handle& other) { | |
99 MojoHandle temp = value_; | |
100 value_ = other.value_; | |
101 other.value_ = temp; | |
102 } | |
103 | |
104 bool is_valid() const { | |
105 return value_ != MOJO_HANDLE_INVALID; | |
106 } | |
107 | |
108 MojoHandle value() const { return value_; } | |
109 MojoHandle* mutable_value() { return &value_; } | |
110 void set_value(MojoHandle value) { value_ = value; } | |
111 | |
112 private: | |
113 MojoHandle value_; | |
114 | |
115 // Copying and assignment allowed. | |
116 }; | |
117 | |
118 // Should have zero overhead. | |
119 MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle), | |
120 bad_size_for_cpp_Handle); | |
121 | |
122 // The scoper should also impose no more overhead. | |
123 typedef ScopedHandleBase<Handle> ScopedHandle; | |
124 MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle), | |
125 bad_size_for_cpp_ScopedHandle); | |
126 | |
127 inline MojoResult Wait(const Handle& handle, | |
128 MojoWaitFlags flags, | |
129 MojoDeadline deadline) { | |
130 return MojoWait(handle.value(), flags, deadline); | |
131 } | |
132 | |
133 // |HandleVectorType| and |FlagsVectorType| should be similar enough to | |
134 // |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively: | |
135 // - They should have a (const) |size()| method that returns an unsigned type. | |
136 // - They must provide contiguous storage, with access via (const) reference to | |
137 // that storage provided by a (const) |operator[]()| (by reference). | |
138 template <class HandleVectorType, class FlagsVectorType> | |
139 inline MojoResult WaitMany(const HandleVectorType& handles, | |
140 const FlagsVectorType& flags, | |
141 MojoDeadline deadline) { | |
142 if (flags.size() != handles.size()) | |
143 return MOJO_RESULT_INVALID_ARGUMENT; | |
144 if (handles.size() > std::numeric_limits<uint32_t>::max()) | |
145 return MOJO_RESULT_OUT_OF_RANGE; | |
146 | |
147 if (handles.size() == 0) | |
148 return MojoWaitMany(NULL, NULL, 0, deadline); | |
149 | |
150 const Handle& first_handle = handles[0]; | |
151 const MojoWaitFlags& first_flag = flags[0]; | |
152 return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle), | |
153 reinterpret_cast<const MojoWaitFlags*>(&first_flag), | |
154 static_cast<uint32_t>(handles.size()), | |
155 deadline); | |
156 } | |
157 | |
158 // |Close()| takes ownership of the handle, since it'll invalidate it. | |
159 // Note: There's nothing to do, since the argument will be destroyed when it | |
160 // goes out of scope. | |
161 template <class HandleType> | |
162 inline void Close(ScopedHandleBase<HandleType> /*handle*/) {} | |
163 | |
164 // Most users should typically use |Close()| (above) instead. | |
165 inline MojoResult CloseRaw(Handle handle) { | |
166 return MojoClose(handle.value()); | |
167 } | |
168 | |
169 // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s, | |
170 // etc. | |
171 inline bool operator<(const Handle& a, const Handle& b) { | |
172 return a.value() < b.value(); | |
173 } | |
174 | |
175 // MessagePipeHandle ----------------------------------------------------------- | |
176 | |
177 class MessagePipeHandle : public Handle { | |
178 public: | |
179 MessagePipeHandle() {} | |
180 explicit MessagePipeHandle(MojoHandle value) : Handle(value) {} | |
181 | |
182 // Copying and assignment allowed. | |
183 }; | |
184 | |
185 MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle), | |
186 bad_size_for_cpp_MessagePipeHandle); | |
187 | |
188 typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle; | |
189 MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) == | |
190 sizeof(MessagePipeHandle), | |
191 bad_size_for_cpp_ScopedMessagePipeHandle); | |
192 | |
193 inline MojoResult CreateMessagePipe(ScopedMessagePipeHandle* message_pipe0, | |
194 ScopedMessagePipeHandle* message_pipe1) { | |
195 assert(message_pipe0); | |
196 assert(message_pipe1); | |
197 MessagePipeHandle handle0; | |
198 MessagePipeHandle handle1; | |
199 MojoResult rv = MojoCreateMessagePipe(handle0.mutable_value(), | |
200 handle1.mutable_value()); | |
201 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
202 // will be used). | |
203 message_pipe0->reset(handle0); | |
204 message_pipe1->reset(handle1); | |
205 return rv; | |
206 } | |
207 | |
208 // These "raw" versions fully expose the underlying API, but don't help with | |
209 // ownership of handles (especially when writing messages). | |
210 // TODO(vtl): Write "baked" versions. | |
211 inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe, | |
212 const void* bytes, | |
213 uint32_t num_bytes, | |
214 const MojoHandle* handles, | |
215 uint32_t num_handles, | |
216 MojoWriteMessageFlags flags) { | |
217 return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles, | |
218 num_handles, flags); | |
219 } | |
220 | |
221 inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe, | |
222 void* bytes, | |
223 uint32_t* num_bytes, | |
224 MojoHandle* handles, | |
225 uint32_t* num_handles, | |
226 MojoReadMessageFlags flags) { | |
227 return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles, | |
228 num_handles, flags); | |
229 } | |
230 | |
231 // A wrapper class that automatically creates a message pipe and owns both | |
232 // handles. | |
233 class MessagePipe { | |
234 public: | |
235 MessagePipe(); | |
236 ~MessagePipe(); | |
237 | |
238 ScopedMessagePipeHandle handle0; | |
239 ScopedMessagePipeHandle handle1; | |
240 }; | |
241 | |
242 inline MessagePipe::MessagePipe() { | |
243 MojoResult result MOJO_ALLOW_UNUSED = CreateMessagePipe(&handle0, &handle1); | |
244 assert(result == MOJO_RESULT_OK); | |
245 } | |
246 | |
247 inline MessagePipe::~MessagePipe() { | |
248 } | |
249 | |
250 // DataPipeProducerHandle and DataPipeConsumerHandle --------------------------- | |
251 | |
252 class DataPipeProducerHandle : public Handle { | |
253 public: | |
254 DataPipeProducerHandle() {} | |
255 explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {} | |
256 | |
257 // Copying and assignment allowed. | |
258 }; | |
259 | |
260 MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle), | |
261 bad_size_for_cpp_DataPipeProducerHandle); | |
262 | |
263 typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle; | |
264 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) == | |
265 sizeof(DataPipeProducerHandle), | |
266 bad_size_for_cpp_ScopedDataPipeProducerHandle); | |
267 | |
268 class DataPipeConsumerHandle : public Handle { | |
269 public: | |
270 DataPipeConsumerHandle() {} | |
271 explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {} | |
272 | |
273 // Copying and assignment allowed. | |
274 }; | |
275 | |
276 MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle), | |
277 bad_size_for_cpp_DataPipeConsumerHandle); | |
278 | |
279 typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle; | |
280 MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) == | |
281 sizeof(DataPipeConsumerHandle), | |
282 bad_size_for_cpp_ScopedDataPipeConsumerHandle); | |
283 | |
284 inline MojoResult CreateDataPipe( | |
285 const MojoCreateDataPipeOptions* options, | |
286 ScopedDataPipeProducerHandle* data_pipe_producer, | |
287 ScopedDataPipeConsumerHandle* data_pipe_consumer) { | |
288 assert(data_pipe_producer); | |
289 assert(data_pipe_consumer); | |
290 DataPipeProducerHandle producer_handle; | |
291 DataPipeConsumerHandle consumer_handle; | |
292 MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(), | |
293 consumer_handle.mutable_value()); | |
294 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
295 // will be used). | |
296 data_pipe_producer->reset(producer_handle); | |
297 data_pipe_consumer->reset(consumer_handle); | |
298 return rv; | |
299 } | |
300 | |
301 inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
302 const void* elements, | |
303 uint32_t* num_bytes, | |
304 MojoWriteDataFlags flags) { | |
305 return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags); | |
306 } | |
307 | |
308 inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
309 void** buffer, | |
310 uint32_t* buffer_num_bytes, | |
311 MojoWriteDataFlags flags) { | |
312 return MojoBeginWriteData(data_pipe_producer.value(), buffer, | |
313 buffer_num_bytes, flags); | |
314 } | |
315 | |
316 inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer, | |
317 uint32_t num_bytes_written) { | |
318 return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written); | |
319 } | |
320 | |
321 inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
322 void* elements, | |
323 uint32_t* num_bytes, | |
324 MojoReadDataFlags flags) { | |
325 return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags); | |
326 } | |
327 | |
328 inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
329 const void** buffer, | |
330 uint32_t* buffer_num_bytes, | |
331 MojoReadDataFlags flags) { | |
332 return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes, | |
333 flags); | |
334 } | |
335 | |
336 inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer, | |
337 uint32_t num_bytes_read) { | |
338 return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read); | |
339 } | |
340 | |
341 // A wrapper class that automatically creates a data pipe and owns both handles. | |
342 // TODO(vtl): Make an even more friendly version? (Maybe templatized for a | |
343 // particular type instead of some "element"? Maybe functions that take | |
344 // vectors?) | |
345 class DataPipe { | |
346 public: | |
347 DataPipe(); | |
348 explicit DataPipe(const MojoCreateDataPipeOptions& options); | |
349 ~DataPipe(); | |
350 | |
351 ScopedDataPipeProducerHandle producer_handle; | |
352 ScopedDataPipeConsumerHandle consumer_handle; | |
353 }; | |
354 | |
355 inline DataPipe::DataPipe() { | |
356 MojoResult result MOJO_ALLOW_UNUSED = | |
357 CreateDataPipe(NULL, &producer_handle, &consumer_handle); | |
358 assert(result == MOJO_RESULT_OK); | |
359 } | |
360 | |
361 inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) { | |
362 MojoResult result MOJO_ALLOW_UNUSED = | |
363 CreateDataPipe(&options, &producer_handle, &consumer_handle); | |
364 assert(result == MOJO_RESULT_OK); | |
365 } | |
366 | |
367 inline DataPipe::~DataPipe() { | |
368 } | |
369 | |
370 // SharedBufferHandle ---------------------------------------------------------- | |
371 | |
372 class SharedBufferHandle : public Handle { | |
373 public: | |
374 SharedBufferHandle() {} | |
375 explicit SharedBufferHandle(MojoHandle value) : Handle(value) {} | |
376 | |
377 // Copying and assignment allowed. | |
378 }; | |
379 | |
380 MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle), | |
381 bad_size_for_cpp_SharedBufferHandle); | |
382 | |
383 typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle; | |
384 MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) == | |
385 sizeof(SharedBufferHandle), | |
386 bad_size_for_cpp_ScopedSharedBufferHandle); | |
387 | |
388 inline MojoResult CreateSharedBuffer( | |
389 const MojoCreateSharedBufferOptions* options, | |
390 uint64_t num_bytes, | |
391 ScopedSharedBufferHandle* shared_buffer) { | |
392 assert(shared_buffer); | |
393 SharedBufferHandle handle; | |
394 MojoResult rv = MojoCreateSharedBuffer(options, num_bytes, | |
395 handle.mutable_value()); | |
396 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
397 // will be used). | |
398 shared_buffer->reset(handle); | |
399 return rv; | |
400 } | |
401 | |
402 // TODO(vtl): This (and also the functions below) are templatized to allow for | |
403 // future/other buffer types. A bit "safer" would be to overload this function | |
404 // manually. (The template enforces that the in and out handles to be of the | |
405 // same type.) | |
406 template <class BufferHandleType> | |
407 inline MojoResult DuplicatedBuffer( | |
408 BufferHandleType buffer, | |
409 const MojoDuplicateBufferHandleOptions* options, | |
410 ScopedHandleBase<BufferHandleType>* new_buffer) { | |
411 assert(new_buffer); | |
412 BufferHandleType handle; | |
413 MojoResult rv = MojoDuplicateSharedBuffer(buffer.value(), options, | |
414 handle.mutable_value()); | |
415 // Reset even on failure (reduces the chances that a "stale"/incorrect handle | |
416 // will be used). | |
417 new_buffer->reset(handle); | |
418 return rv; | |
419 } | |
420 | |
421 template <class BufferHandleType> | |
422 inline MojoResult MapBuffer(BufferHandleType buffer, | |
423 uint64_t offset, | |
424 uint64_t num_bytes, | |
425 void** pointer, | |
426 MojoMapBufferFlags flags) { | |
427 assert(buffer); | |
428 return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags); | |
429 } | |
430 | |
431 inline MojoResult UnmapBuffer(void* pointer) { | |
432 assert(pointer); | |
433 return MojoUnmapBuffer(pointer); | |
434 } | |
435 | |
436 // A wrapper class that automatically creates a shared buffer and owns the | |
437 // handle. | |
438 class SharedBuffer { | |
439 public: | |
440 explicit SharedBuffer(uint64_t num_bytes); | |
441 SharedBuffer(uint64_t num_bytes, | |
442 const MojoCreateSharedBufferOptions& options); | |
443 ~SharedBuffer(); | |
444 | |
445 ScopedSharedBufferHandle handle; | |
446 }; | |
447 | |
448 inline SharedBuffer::SharedBuffer(uint64_t num_bytes) { | |
449 MojoResult result MOJO_ALLOW_UNUSED = | |
450 CreateSharedBuffer(NULL, num_bytes, &handle); | |
451 assert(result == MOJO_RESULT_OK); | |
452 } | |
453 | |
454 inline SharedBuffer::SharedBuffer( | |
455 uint64_t num_bytes, | |
456 const MojoCreateSharedBufferOptions& options) { | |
457 MojoResult result MOJO_ALLOW_UNUSED = | |
458 CreateSharedBuffer(&options, num_bytes, &handle); | |
459 assert(result == MOJO_RESULT_OK); | |
460 } | |
461 | |
462 inline SharedBuffer::~SharedBuffer() { | |
463 } | |
464 | |
465 } // namespace mojo | |
466 | |
467 #endif // MOJO_PUBLIC_SYSTEM_CORE_CPP_H_ | |
OLD | NEW |