Skip to content

Commit

Permalink
Mojo: Add a C++-style SharedBuffer API.
Browse files Browse the repository at this point in the history
Review-Url: https://codereview.chromium.org/2036053002
Cr-Commit-Position: refs/heads/master@{#397957}
  • Loading branch information
sammc authored and Commit bot committed Jun 6, 2016
1 parent 851eb42 commit a7ee0a2
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 2 deletions.
1 change: 1 addition & 0 deletions mojo/mojo_public.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
'target_name': 'mojo_cpp_system',
'type': 'static_library',
'sources': [
'public/cpp/system/buffer.cc',
'public/cpp/system/buffer.h',
'public/cpp/system/core.h',
'public/cpp/system/data_pipe.h',
Expand Down
1 change: 1 addition & 0 deletions mojo/public/cpp/system/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

source_set("system") {
sources = [
"buffer.cc",
"buffer.h",
"core.h",
"data_pipe.h",
Expand Down
37 changes: 37 additions & 0 deletions mojo/public/cpp/system/buffer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2016 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.

#include "mojo/public/cpp/system/buffer.h"

namespace mojo {

ScopedSharedBufferHandle SharedBufferHandle::Clone(
SharedBufferHandle::AccessMode access_mode) const {
ScopedSharedBufferHandle result;
if (!is_valid())
return result;

MojoDuplicateBufferHandleOptions options = {
sizeof(options), MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
if (access_mode == AccessMode::READ_ONLY)
options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY;
SharedBufferHandle result_handle;
MojoDuplicateBufferHandle(value(), &options, result_handle.mutable_value());
result.reset(result_handle);
return result;
}

ScopedSharedBufferMapping SharedBufferHandle::Map(uint64_t size) const {
return MapAtOffset(size, 0);
}

ScopedSharedBufferMapping SharedBufferHandle::MapAtOffset(
uint64_t size,
uint64_t offset) const {
void* buffer = nullptr;
MojoMapBuffer(value(), offset, size, &buffer, MOJO_MAP_BUFFER_FLAG_NONE);
return ScopedSharedBufferMapping(buffer);
}

} // namespace mojo
38 changes: 36 additions & 2 deletions mojo/public/cpp/system/buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,61 @@

#include <stdint.h>

#include <memory>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/cpp/system/handle.h"

namespace mojo {
namespace internal {

struct Unmapper {
void operator()(void* buffer) {
MojoResult result = MojoUnmapBuffer(buffer);
DCHECK_EQ(MOJO_RESULT_OK, result);
}
};

} // namespace internal

using ScopedSharedBufferMapping = std::unique_ptr<void, internal::Unmapper>;

class SharedBufferHandle;

typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;

// A strongly-typed representation of a |MojoHandle| referring to a shared
// buffer.
class SharedBufferHandle : public Handle {
public:
enum class AccessMode {
READ_WRITE,
READ_ONLY,
};

SharedBufferHandle() {}
explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}

// Copying and assignment allowed.

// Clones this shared buffer handle. If |access_mode| is READ_ONLY or this is
// a read-only handle, the new handle will be read-only. On failure, this will
// return an empty result.
ScopedSharedBufferHandle Clone(AccessMode = AccessMode::READ_WRITE) const;

// Maps |size| bytes of this shared buffer. On failure, this will return a
// null mapping.
ScopedSharedBufferMapping Map(uint64_t size) const;

// Maps |size| bytes of this shared buffer, starting |offset| bytes into the
// buffer. On failure, this will return a null mapping.
ScopedSharedBufferMapping MapAtOffset(uint64_t size, uint64_t offset) const;
};

static_assert(sizeof(SharedBufferHandle) == sizeof(Handle),
"Bad size for C++ SharedBufferHandle");

typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
static_assert(sizeof(ScopedSharedBufferHandle) == sizeof(SharedBufferHandle),
"Bad size for C++ ScopedSharedBufferHandle");

Expand Down
1 change: 1 addition & 0 deletions mojo/public/cpp/system/handle.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class ScopedHandleBase {
}

const HandleType& get() const { return handle_; }
const HandleType* operator->() const { return &handle_; }

template <typename PassedHandleType>
static ScopedHandleBase<HandleType> From(
Expand Down
41 changes: 41 additions & 0 deletions mojo/public/cpp/system/tests/core_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,47 @@ TEST(CoreCppTest, ScopedHandleMoveCtor) {
EXPECT_FALSE(buffer2.is_valid());
}

TEST(CoreCppTest, BasicSharedBuffer) {
ScopedSharedBufferHandle h0;

// Create a shared buffer (|h0|).
{
SharedBuffer buffer(100);
h0 = std::move(buffer.handle);
}

// Map everything.
ScopedSharedBufferMapping mapping = h0->Map(100);
ASSERT_TRUE(mapping);
static_cast<char*>(mapping.get())[50] = 'x';

// Duplicate |h0| to |h1|.
ScopedSharedBufferHandle h1 =
h0->Clone(SharedBufferHandle::AccessMode::READ_ONLY);
ASSERT_TRUE(h1.is_valid());

// Close |h0|.
h0.reset();

// The mapping should still be good.
static_cast<char*>(mapping.get())[51] = 'y';

// Unmap it.
mapping.reset();

// Map half of |h1|.
mapping = h1->MapAtOffset(50, 50);
ASSERT_TRUE(mapping);

// It should have what we wrote.
EXPECT_EQ('x', static_cast<char*>(mapping.get())[0]);
EXPECT_EQ('y', static_cast<char*>(mapping.get())[1]);

// Unmap it.
mapping.reset();
h1.reset();
}

// TODO(vtl): Write data pipe tests.

} // namespace
Expand Down

0 comments on commit a7ee0a2

Please sign in to comment.