blob: 2a83862bd98cf2240b10fe258fe53a106df128a6 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
#define MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
#include <assert.h>
#include <limits>
#include "mojo/public/system/core.h"
#include "mojo/public/system/macros.h"
#include "mojo/public/system/system_export.h"
namespace mojo {
// ScopedHandleBase ------------------------------------------------------------
// Scoper for the actual handle types defined further below. It's move-only,
// like the C++11 |unique_ptr|.
template <class HandleType>
class ScopedHandleBase {
MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue);
public:
ScopedHandleBase() {}
explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
~ScopedHandleBase() { CloseIfNecessary(); }
// Move-only constructor and operator=.
ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
ScopedHandleBase& operator=(RValue other) {
handle_ = other.object->release();
return *this;
}
const HandleType& get() const { return handle_; }
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);
}
// Handle ----------------------------------------------------------------------
const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
// Wrapper base class for |MojoHandle|.
class Handle {
public:
Handle() : value_(MOJO_HANDLE_INVALID) {}
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_ != MOJO_HANDLE_INVALID;
}
MojoHandle value() const { return value_; }
MojoHandle* mutable_value() { return &value_; }
void set_value(MojoHandle value) { value_ = value; }
private:
MojoHandle value_;
// Copying and assignment allowed.
};
// Should have zero overhead.
MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
bad_size_for_cpp_Handle);
// The scoper should also impose no more overhead.
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);
}
// |HandleVectorType| and |FlagsVectorType| should be similar enough to
// |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively:
// - They should have a (const) |size()| method that returns an unsigned type.
// - They must provide contiguous storage, with access via (const) reference to
// that storage provided by a (const) |operator[]()| (by reference).
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);
}
// |Close()| takes ownership of the handle, since it'll invalidate it.
// Note: There's nothing to do, since the argument will be destroyed when it
// goes out of scope.
template <class HandleType>
inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
// Most users should typically use |Close()| (above) instead.
inline MojoResult CloseRaw(Handle handle) {
return MojoClose(handle.value());
}
// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
// etc.
inline bool operator<(const Handle& a, const Handle& b) {
return a.value() < b.value();
}
// MessagePipeHandle -----------------------------------------------------------
class MessagePipeHandle : public Handle {
public:
MessagePipeHandle() {}
explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
// Copying and assignment allowed.
};
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);
// TODO(vtl): In C++11, we could instead return a pair of
// |ScopedHandleBase<MessagePipeHandle>|s.
inline void CreateMessagePipe(ScopedMessagePipeHandle* message_pipe_0,
ScopedMessagePipeHandle* message_pipe_1) {
assert(message_pipe_0);
assert(message_pipe_1);
MessagePipeHandle h_0;
MessagePipeHandle h_1;
MojoResult result MOJO_ALLOW_UNUSED =
MojoCreateMessagePipe(h_0.mutable_value(), h_1.mutable_value());
assert(result == MOJO_RESULT_OK);
message_pipe_0->reset(h_0);
message_pipe_1->reset(h_1);
}
// These "raw" versions fully expose the underlying API, but don't help with
// ownership of handles (especially when writing messages).
// TODO(vtl): Write "baked" versions.
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);
}
inline MojoTimeTicks GetTimeTicksNow() {
return MojoGetTimeTicksNow();
}
} // namespace mojo
#endif // MOJO_PUBLIC_SYSTEM_CORE_CPP_H_