#ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
#define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
#include <assert.h>
#include <stddef.h>
#include <limits>
#include "mojo/public/c/system/core.h"
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
inline MojoTimeTicks GetTimeTicksNow() {
return MojoGetTimeTicksNow();
}
template <class HandleType>
class ScopedHandleBase {
MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue)
public:
ScopedHandleBase() {}
explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
~ScopedHandleBase() { CloseIfNecessary(); }
template <class CompatibleHandleType>
explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
: handle_(other.release()) {
}
ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
ScopedHandleBase& operator=(RValue other) {
handle_ = other.object->release();
return *this;
}
const HandleType& get() const { return handle_; }
template <typename PassedHandleType>
static ScopedHandleBase<HandleType> From(
ScopedHandleBase<PassedHandleType> other) {
MOJO_COMPILE_ASSERT(
sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))),
HandleType_is_not_a_subtype_of_PassedHandleType);
return ScopedHandleBase<HandleType>(
static_cast<HandleType>(other.release().value()));
}
void swap(ScopedHandleBase& other) {
handle_.swap(other.handle_);
}
HandleType release() MOJO_WARN_UNUSED_RESULT {
HandleType rv;
rv.swap(handle_);
return rv;
}
void reset(HandleType handle = HandleType()) {
CloseIfNecessary();
handle_ = handle;
}
bool is_valid() const {
return handle_.is_valid();
}
private:
void CloseIfNecessary() {
if (!handle_.is_valid())
return;
MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
assert(result == MOJO_RESULT_OK);
}
HandleType handle_;
};
template <typename HandleType>
inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
return ScopedHandleBase<HandleType>(handle);
}
const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
class Handle {
public:
Handle() : value_(kInvalidHandleValue) {}
explicit Handle(MojoHandle value) : value_(value) {}
~Handle() {}
void swap(Handle& other) {
MojoHandle temp = value_;
value_ = other.value_;
other.value_ = temp;
}
bool is_valid() const {
return value_ != kInvalidHandleValue;
}
MojoHandle value() const { return value_; }
MojoHandle* mutable_value() { return &value_; }
void set_value(MojoHandle value) { value_ = value; }
private:
MojoHandle value_;
};
MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
bad_size_for_cpp_Handle);
typedef ScopedHandleBase<Handle> ScopedHandle;
MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
bad_size_for_cpp_ScopedHandle);
inline MojoResult Wait(const Handle& handle,
MojoWaitFlags flags,
MojoDeadline deadline) {
return MojoWait(handle.value(), flags, deadline);
}
template <class HandleVectorType, class FlagsVectorType>
inline MojoResult WaitMany(const HandleVectorType& handles,
const FlagsVectorType& flags,
MojoDeadline deadline) {
if (flags.size() != handles.size())
return MOJO_RESULT_INVALID_ARGUMENT;
if (handles.size() > std::numeric_limits<uint32_t>::max())
return MOJO_RESULT_OUT_OF_RANGE;
if (handles.size() == 0)
return MojoWaitMany(NULL, NULL, 0, deadline);
const Handle& first_handle = handles[0];
const MojoWaitFlags& first_flag = flags[0];
return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle),
reinterpret_cast<const MojoWaitFlags*>(&first_flag),
static_cast<uint32_t>(handles.size()),
deadline);
}
template <class HandleType>
inline void Close(ScopedHandleBase<HandleType> ) {}
inline MojoResult CloseRaw(Handle handle) {
return MojoClose(handle.value());
}
inline bool operator<(const Handle& a, const Handle& b) {
return a.value() < b.value();
}
class MessagePipeHandle : public Handle {
public:
MessagePipeHandle() {}
explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
};
MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
bad_size_for_cpp_MessagePipeHandle);
typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
sizeof(MessagePipeHandle),
bad_size_for_cpp_ScopedMessagePipeHandle);
inline MojoResult CreateMessagePipe(ScopedMessagePipeHandle* message_pipe0,
ScopedMessagePipeHandle* message_pipe1) {
assert(message_pipe0);
assert(message_pipe1);
MessagePipeHandle handle0;
MessagePipeHandle handle1;
MojoResult rv = MojoCreateMessagePipe(handle0.mutable_value(),
handle1.mutable_value());
message_pipe0->reset(handle0);
message_pipe1->reset(handle1);
return rv;
}
inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe,
const void* bytes,
uint32_t num_bytes,
const MojoHandle* handles,
uint32_t num_handles,
MojoWriteMessageFlags flags) {
return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles,
num_handles, flags);
}
inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
void* bytes,
uint32_t* num_bytes,
MojoHandle* handles,
uint32_t* num_handles,
MojoReadMessageFlags flags) {
return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles,
num_handles, flags);
}
class MessagePipe {
public:
MessagePipe();
~MessagePipe();
ScopedMessagePipeHandle handle0;
ScopedMessagePipeHandle handle1;
};
inline MessagePipe::MessagePipe() {
MojoResult result MOJO_ALLOW_UNUSED = CreateMessagePipe(&handle0, &handle1);
assert(result == MOJO_RESULT_OK);
}
inline MessagePipe::~MessagePipe() {
}
class DataPipeProducerHandle : public Handle {
public:
DataPipeProducerHandle() {}
explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
};
MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
bad_size_for_cpp_DataPipeProducerHandle);
typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
sizeof(DataPipeProducerHandle),
bad_size_for_cpp_ScopedDataPipeProducerHandle);
class DataPipeConsumerHandle : public Handle {
public:
DataPipeConsumerHandle() {}
explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
};
MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
bad_size_for_cpp_DataPipeConsumerHandle);
typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
sizeof(DataPipeConsumerHandle),
bad_size_for_cpp_ScopedDataPipeConsumerHandle);
inline MojoResult CreateDataPipe(
const MojoCreateDataPipeOptions* options,
ScopedDataPipeProducerHandle* data_pipe_producer,
ScopedDataPipeConsumerHandle* data_pipe_consumer) {
assert(data_pipe_producer);
assert(data_pipe_consumer);
DataPipeProducerHandle producer_handle;
DataPipeConsumerHandle consumer_handle;
MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(),
consumer_handle.mutable_value());
data_pipe_producer->reset(producer_handle);
data_pipe_consumer->reset(consumer_handle);
return rv;
}
inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
const void* elements,
uint32_t* num_bytes,
MojoWriteDataFlags flags) {
return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
}
inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
void** buffer,
uint32_t* buffer_num_bytes,
MojoWriteDataFlags flags) {
return MojoBeginWriteData(data_pipe_producer.value(), buffer,
buffer_num_bytes, flags);
}
inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
uint32_t num_bytes_written) {
return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
}
inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
void* elements,
uint32_t* num_bytes,
MojoReadDataFlags flags) {
return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
}
inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
const void** buffer,
uint32_t* buffer_num_bytes,
MojoReadDataFlags flags) {
return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes,
flags);
}
inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
uint32_t num_bytes_read) {
return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
}
class DataPipe {
public:
DataPipe();
explicit DataPipe(const MojoCreateDataPipeOptions& options);
~DataPipe();
ScopedDataPipeProducerHandle producer_handle;
ScopedDataPipeConsumerHandle consumer_handle;
};
inline DataPipe::DataPipe() {
MojoResult result MOJO_ALLOW_UNUSED =
CreateDataPipe(NULL, &producer_handle, &consumer_handle);
assert(result == MOJO_RESULT_OK);
}
inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
MojoResult result MOJO_ALLOW_UNUSED =
CreateDataPipe(&options, &producer_handle, &consumer_handle);
assert(result == MOJO_RESULT_OK);
}
inline DataPipe::~DataPipe() {
}
class SharedBufferHandle : public Handle {
public:
SharedBufferHandle() {}
explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
};
MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
bad_size_for_cpp_SharedBufferHandle);
typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
sizeof(SharedBufferHandle),
bad_size_for_cpp_ScopedSharedBufferHandle);
inline MojoResult CreateSharedBuffer(
const MojoCreateSharedBufferOptions* options,
uint64_t num_bytes,
ScopedSharedBufferHandle* shared_buffer) {
assert(shared_buffer);
SharedBufferHandle handle;
MojoResult rv = MojoCreateSharedBuffer(options, num_bytes,
handle.mutable_value());
shared_buffer->reset(handle);
return rv;
}
template <class BufferHandleType>
inline MojoResult DuplicateBuffer(
BufferHandleType buffer,
const MojoDuplicateBufferHandleOptions* options,
ScopedHandleBase<BufferHandleType>* new_buffer) {
assert(new_buffer);
BufferHandleType handle;
MojoResult rv = MojoDuplicateBufferHandle(
buffer.value(), options, handle.mutable_value());
new_buffer->reset(handle);
return rv;
}
template <class BufferHandleType>
inline MojoResult MapBuffer(BufferHandleType buffer,
uint64_t offset,
uint64_t num_bytes,
void** pointer,
MojoMapBufferFlags flags) {
assert(buffer.is_valid());
return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags);
}
inline MojoResult UnmapBuffer(void* pointer) {
assert(pointer);
return MojoUnmapBuffer(pointer);
}
class SharedBuffer {
public:
explicit SharedBuffer(uint64_t num_bytes);
SharedBuffer(uint64_t num_bytes,
const MojoCreateSharedBufferOptions& options);
~SharedBuffer();
ScopedSharedBufferHandle handle;
};
inline SharedBuffer::SharedBuffer(uint64_t num_bytes) {
MojoResult result MOJO_ALLOW_UNUSED =
CreateSharedBuffer(NULL, num_bytes, &handle);
assert(result == MOJO_RESULT_OK);
}
inline SharedBuffer::SharedBuffer(
uint64_t num_bytes,
const MojoCreateSharedBufferOptions& options) {
MojoResult result MOJO_ALLOW_UNUSED =
CreateSharedBuffer(&options, num_bytes, &handle);
assert(result == MOJO_RESULT_OK);
}
inline SharedBuffer::~SharedBuffer() {
}
}
#endif