Update to mojo dd010e1297c09b351dc82f7def154cfa63d795b1

This commit is contained in:
Collin Jackson 2015-11-06 14:15:04 -08:00
parent 8f06f346ee
commit 0847bbc2d0
197 changed files with 4999 additions and 2341 deletions

View File

@ -129,7 +129,6 @@ shared_library("mojo_java_unittests") {
"//mojo/message_pump",
"//mojo/public/cpp/bindings/tests:mojo_public_bindings_test_utils",
"//mojo/public/cpp/environment",
"//mojo/public/cpp/test_support:test_utils",
]
defines = [ "UNIT_TEST" ]
}

View File

@ -9,8 +9,7 @@ source_set("common") {
sources = [
"binding_set.h",
"interface_ptr_set.h",
"task_tracker.cc",
"task_tracker.h",
"strong_binding_set.h",
]
deps = [
@ -19,34 +18,38 @@ source_set("common") {
]
}
test("mojo_common_unittests") {
source_set("tests") {
testonly = true
sources = [
"binding_set_unittest.cc",
"callback_binding_unittest.cc",
"interface_ptr_set_unittest.cc",
"task_tracker_unittest.cc",
"strong_binding_set_unittest.cc",
]
deps = [
":common",
":test_interfaces",
"//base",
"//base/test:test_support",
"//mojo/message_pump",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/system",
"//testing/gtest",
]
}
test("mojo_common_unittests") {
deps = [
":tests",
"//mojo/converters/array_string:tests",
"//mojo/converters/base:tests",
"//mojo/converters/url:tests",
"//mojo/data_pipe_utils:tests",
"//mojo/edk/test:run_all_unittests",
"//mojo/edk/test:test_support",
"//mojo/environment:chromium",
"//mojo/message_pump",
"//mojo/message_pump:tests",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/system",
"//mojo/public/cpp/test_support:test_utils",
"//testing/gtest",
"//url",
]
}

View File

@ -6,9 +6,11 @@
#define MOJO_COMMON_BINDING_SET_H_
#include <algorithm>
#include <memory>
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/logging.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace mojo {
@ -21,6 +23,9 @@ class BindingSet {
BindingSet() {}
~BindingSet() { CloseAllBindings(); }
// Adds a binding to the list and arranges for it to be removed when
// a connection error occurs. Does not take ownership of |impl|, which
// must outlive the binding set.
void AddBinding(Interface* impl, InterfaceRequest<Interface> request) {
bindings_.emplace_back(new Binding<Interface>(impl, request.Pass()));
auto* binding = bindings_.back().get();

View File

@ -0,0 +1,65 @@
// Copyright 2014 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_COMMON_STRONG_BINDING_SET_H_
#define MOJO_COMMON_STRONG_BINDING_SET_H_
#include <algorithm>
#include <memory>
#include <vector>
#include "base/logging.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace mojo {
// Use this class to manage a set of strong bindings each of which is
// owned by the pipe it is bound to. The set takes ownership of the
// interfaces and will delete them when the bindings are closed.
template <typename Interface>
class StrongBindingSet {
public:
StrongBindingSet() {}
~StrongBindingSet() { CloseAllBindings(); }
// Adds a binding to the list and arranges for it to be removed when
// a connection error occurs. Takes ownership of |impl|, which
// will be deleted when the binding is closed.
void AddBinding(Interface* impl, InterfaceRequest<Interface> request) {
bindings_.emplace_back(new Binding<Interface>(impl, request.Pass()));
auto* binding = bindings_.back().get();
// Set the connection error handler for the newly added Binding to be a
// function that will erase it from the vector.
binding->set_connection_error_handler([this, binding]() {
auto it =
std::find_if(bindings_.begin(), bindings_.end(),
[binding](const std::unique_ptr<Binding<Interface>>& b) {
return (b.get() == binding);
});
DCHECK(it != bindings_.end());
delete binding->impl();
bindings_.erase(it);
});
}
// Closes all bindings and deletes their associated interfaces.
void CloseAllBindings() {
for (auto it = bindings_.begin(); it != bindings_.end(); ++it) {
delete (*it)->impl();
}
bindings_.clear();
}
size_t size() const { return bindings_.size(); }
private:
std::vector<std::unique_ptr<Binding<Interface>>> bindings_;
DISALLOW_COPY_AND_ASSIGN(StrongBindingSet);
};
} // namespace mojo
#endif // MOJO_COMMON_STRONG_BINDING_SET_H_

View File

@ -0,0 +1,115 @@
// Copyright 2015 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/common/strong_binding_set.h"
#include "base/message_loop/message_loop.h"
#include "mojo/common/test_interfaces.mojom.h"
#include "mojo/message_pump/message_pump_mojo.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace common {
namespace {
class DummyImpl : public tests::Dummy {
public:
explicit DummyImpl(bool* deleted_flag) : deleted_flag_(deleted_flag) {}
~DummyImpl() override { *deleted_flag_ = true; }
void Foo() override { call_count_++; }
int call_count() const { return call_count_; }
private:
bool* deleted_flag_;
int call_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(DummyImpl);
};
// Tests all of the functionality of StrongBindingSet.
TEST(StrongBindingSetTest, FullLifeCycle) {
base::MessageLoop loop(MessagePumpMojo::Create());
// Create 10 InterfacePtrs and DummyImpls.
const size_t kNumObjects = 10;
InterfacePtr<tests::Dummy> intrfc_ptrs[kNumObjects];
DummyImpl* impls[kNumObjects];
bool deleted_flags[kNumObjects] = {};
// Create 10 message pipes, bind everything together, and add the
// bindings to binding_set.
StrongBindingSet<tests::Dummy> binding_set;
EXPECT_EQ(0u, binding_set.size());
for (size_t i = 0; i < kNumObjects; i++) {
impls[i] = new DummyImpl(&deleted_flags[i]);
binding_set.AddBinding(impls[i], GetProxy(&intrfc_ptrs[i]));
}
EXPECT_EQ(kNumObjects, binding_set.size());
// Check that initially all call counts are zero.
for (const auto& impl : impls) {
EXPECT_EQ(0, impl->call_count());
}
// Invoke method foo() on all 10 InterfacePointers.
for (InterfacePtr<tests::Dummy>& ptr : intrfc_ptrs) {
ptr->Foo();
}
// Check that now all call counts are one.
loop.RunUntilIdle();
for (const auto& impl : impls) {
EXPECT_EQ(1, impl->call_count());
}
// Close the first 5 message pipes and destroy the first five
// InterfacePtrs.
for (size_t i = 0; i < kNumObjects / 2; i++) {
intrfc_ptrs[i].reset();
}
// Check that the set contains only five elements now.
loop.RunUntilIdle();
EXPECT_EQ(kNumObjects / 2, binding_set.size());
// Check that the first 5 interfaces have all been deleted.
for (size_t i = 0; i < kNumObjects; i++) {
bool expected = (i < kNumObjects / 2);
EXPECT_EQ(expected, deleted_flags[i]);
}
// Invoke method foo() on the second five InterfacePointers.
for (size_t i = kNumObjects / 2; i < kNumObjects; i++) {
intrfc_ptrs[i]->Foo();
}
loop.RunUntilIdle();
// Check that now the second five counts are two.
for (size_t i = kNumObjects / 2; i < kNumObjects; i++) {
EXPECT_EQ(2, impls[i]->call_count());
}
// Invoke CloseAllBindings
binding_set.CloseAllBindings();
EXPECT_EQ(0u, binding_set.size());
// Invoke method foo() on the second five InterfacePointers.
for (size_t i = kNumObjects / 2; i < kNumObjects; i++) {
intrfc_ptrs[i]->Foo();
}
loop.RunUntilIdle();
// Check that all interfaces have all been deleted.
for (size_t i = 0; i < kNumObjects; i++) {
EXPECT_TRUE(deleted_flags[i]);
}
}
} // namespace
} // namespace common
} // namespace mojo

View File

@ -1,102 +0,0 @@
// Copyright 2015 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/common/task_tracker.h"
#include <vector>
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/threading/thread_local.h"
#include "base/tracked_objects.h"
namespace mojo {
namespace common {
namespace {
class TrackingActivation {
public:
TrackingActivation() : birth_(nullptr) {}
bool Start(const char* function_name,
const char* file_name,
int line_number,
const void* program_counter);
void End();
bool IsAlive() const { return birth_ != nullptr; }
private:
tracked_objects::TaskStopwatch* stopwatch() {
return reinterpret_cast<tracked_objects::TaskStopwatch*>(stopwatch_heap_);
}
tracked_objects::Births* birth_;
// TaskStopwatch isn't copyable, but we don't want to allocate it on the heap
// so as not to slow things down, hence replacement new.
char stopwatch_heap_[sizeof(tracked_objects::TaskStopwatch)];
DISALLOW_COPY_AND_ASSIGN(TrackingActivation);
};
bool TrackingActivation::Start(const char* function_name,
const char* file_name,
int line_number,
const void* program_counter) {
// So far we don't track nested invocations.
if (IsAlive())
return false;
birth_ = tracked_objects::ThreadData::TallyABirthIfActive(
tracked_objects::Location(function_name, file_name, line_number,
program_counter));
if (!birth_)
return false;
(new (stopwatch()) tracked_objects::TaskStopwatch())->Start();
return true;
}
void TrackingActivation::End() {
DCHECK(IsAlive());
stopwatch()->Stop();
tracked_objects::ThreadData::TallyRunInAScopedRegionIfTracking(birth_,
*stopwatch());
stopwatch()->tracked_objects::TaskStopwatch::~TaskStopwatch();
birth_ = nullptr;
}
base::ThreadLocalPointer<TrackingActivation> g_activation;
} // namespace
// static
intptr_t TaskTracker::StartTracking(const char* function_name,
const char* file_name,
int line_number,
const void* program_counter) {
TrackingActivation* activation = g_activation.Get();
if (!activation) {
// Leak this.
activation = new TrackingActivation();
g_activation.Set(activation);
}
if (!activation->Start(function_name, file_name, line_number,
program_counter))
return 0;
return reinterpret_cast<intptr_t>(activation);
}
// static
void TaskTracker::EndTracking(intptr_t id) {
if (0 == id)
return;
// |EndTracking()| must be called from the same thread of |StartTracking()|.
DCHECK_EQ(reinterpret_cast<TrackingActivation*>(id), g_activation.Get());
reinterpret_cast<TrackingActivation*>(id)->End();
}
} // namespace common
} // namespace mojo

View File

@ -1,26 +0,0 @@
// Copyright 2015 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_COMMON_TASK_TRACKER_H_
#define MOJO_COMMON_TASK_TRACKER_H_
#include <stdint.h>
namespace mojo {
namespace common {
class TaskTracker {
public:
static intptr_t StartTracking(const char* function_name,
const char* file_name,
int line_number,
const void* program_counter);
static void EndTracking(intptr_t id);
static void Enable();
};
} // namespace common
} // namespace mojo
#endif // MOJO_COMMON_TASK_TRACKER_H_

View File

@ -1,54 +0,0 @@
// Copyright 2015 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/common/task_tracker.h"
#include "base/tracked_objects.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace common {
namespace test {
class TaskTrackerTest : public testing::Test {
public:
void SetUp() override {
tracked_objects::ThreadData::InitializeAndSetTrackingStatus(
tracked_objects::ThreadData::PROFILING_ACTIVE);
}
void TearDown() override {
tracked_objects::ThreadData::InitializeAndSetTrackingStatus(
tracked_objects::ThreadData::DEACTIVATED);
}
};
TEST_F(TaskTrackerTest, Nesting) {
intptr_t id0 = TaskTracker::StartTracking("Foo", "foo.cc", 1, nullptr);
intptr_t id1 = TaskTracker::StartTracking("Bar", "bar.cc", 1, nullptr);
TaskTracker::EndTracking(id1);
TaskTracker::EndTracking(id0);
tracked_objects::ProcessDataSnapshot snapshot;
tracked_objects::ThreadData::Snapshot(0, &snapshot);
// Nested one is ignored.
EXPECT_EQ(1U, snapshot.phased_snapshots[0].tasks.size());
}
TEST_F(TaskTrackerTest, Twice) {
intptr_t id0 = TaskTracker::StartTracking("Foo", "foo.cc", 1, nullptr);
TaskTracker::EndTracking(id0);
intptr_t id1 = TaskTracker::StartTracking("Bar", "bar.cc", 1, nullptr);
TaskTracker::EndTracking(id1);
tracked_objects::ProcessDataSnapshot snapshot;
tracked_objects::ThreadData::Snapshot(0, &snapshot);
EXPECT_EQ(2U, snapshot.phased_snapshots[0].tasks.size());
}
} // namespace test
} // namespace common
} // namespace mojo

View File

@ -23,7 +23,7 @@ Array<uint8_t> TypeConverter<Array<uint8_t>, std::string>::Convert(
const std::string& input) {
auto result = Array<uint8_t>::New(input.size());
memcpy(&result.front(), input.c_str(), input.size());
return result.Pass();
return result;
}
} // namespace mojo

View File

@ -11,7 +11,7 @@ PointPtr TypeConverter<PointPtr, gfx::Point>::Convert(const gfx::Point& input) {
PointPtr point(Point::New());
point->x = input.x();
point->y = input.y();
return point.Pass();
return point;
}
// static
@ -27,7 +27,7 @@ PointFPtr TypeConverter<PointFPtr, gfx::PointF>::Convert(
PointFPtr point(PointF::New());
point->x = input.x();
point->y = input.y();
return point.Pass();
return point;
}
// static
@ -43,7 +43,7 @@ SizePtr TypeConverter<SizePtr, gfx::Size>::Convert(const gfx::Size& input) {
SizePtr size(Size::New());
size->width = input.width();
size->height = input.height();
return size.Pass();
return size;
}
// static
@ -60,7 +60,7 @@ RectPtr TypeConverter<RectPtr, gfx::Rect>::Convert(const gfx::Rect& input) {
rect->y = input.y();
rect->width = input.width();
rect->height = input.height();
return rect.Pass();
return rect;
}
// static
@ -77,7 +77,7 @@ RectFPtr TypeConverter<RectFPtr, gfx::RectF>::Convert(const gfx::RectF& input) {
rect->y = input.y();
rect->width = input.width();
rect->height = input.height();
return rect.Pass();
return rect;
}
// static
@ -96,7 +96,7 @@ TransformPtr TypeConverter<TransformPtr, gfx::Transform>::Convert(
matrix.Swap(&storage);
TransformPtr transform(Transform::New());
transform->matrix = matrix.Pass();
return transform.Pass();
return transform;
}
// static

View File

@ -225,7 +225,7 @@ EventPtr TypeConverter<EventPtr, ui::Event>::Convert(const ui::Event& input) {
}
event->key_data = key_data.Pass();
}
return event.Pass();
return event;
}
// static
@ -283,6 +283,7 @@ scoped_ptr<ui::Event> TypeConverter<scoped_ptr<ui::Event>, EventPtr>::Convert(
// TODO: last flags isn't right. Need to send changed_flags.
scoped_ptr<ui::MouseEvent> event(new ui::MouseEvent(
MojoMouseEventTypeToUIEvent(input), location, screen_location,
base::TimeDelta::FromMilliseconds(input->time_stamp),
ui::EventFlags(input->flags), ui::EventFlags(input->flags)));
if (event->IsMouseWheelEvent()) {
// This conversion assumes we're using the mojo meaning of these

View File

@ -14,28 +14,28 @@ namespace mojo {
// NOTE: the mojo input events do not necessarily provide a 1-1 mapping with
// ui::Event types. Be careful in using them!
template <>
struct TypeConverter<EventType, ui::EventType> {
static EventType Convert(ui::EventType type);
struct TypeConverter<EventType, ::ui::EventType> {
static EventType Convert(::ui::EventType type);
};
template <>
struct TypeConverter<EventPtr, ui::Event> {
static EventPtr Convert(const ui::Event& input);
struct TypeConverter<EventPtr, ::ui::Event> {
static EventPtr Convert(const ::ui::Event& input);
};
template <>
struct TypeConverter<EventPtr, ui::KeyEvent> {
static EventPtr Convert(const ui::KeyEvent& input);
struct TypeConverter<EventPtr, ::ui::KeyEvent> {
static EventPtr Convert(const ::ui::KeyEvent& input);
};
template <>
struct TypeConverter<EventPtr, ui::GestureEvent> {
static EventPtr Convert(const ui::GestureEvent& input);
struct TypeConverter<EventPtr, ::ui::GestureEvent> {
static EventPtr Convert(const ::ui::GestureEvent& input);
};
template <>
struct TypeConverter<scoped_ptr<ui::Event>, EventPtr> {
static scoped_ptr<ui::Event> Convert(const EventPtr& input);
struct TypeConverter<scoped_ptr<::ui::Event>, EventPtr> {
static scoped_ptr<::ui::Event> Convert(const EventPtr& input);
};
} // namespace mojo

View File

@ -26,7 +26,7 @@ DisplayModePtr TypeConverter<DisplayModePtr, ui::DisplayMode_Params>::Convert(
out->size = Size::From<gfx::Size>(in.size);
out->is_interlaced = in.is_interlaced;
out->refresh_rate = in.refresh_rate;
return out.Pass();
return out;
}
static_assert(static_cast<int>(ui::DISPLAY_CONNECTION_TYPE_NONE) ==
@ -102,7 +102,7 @@ TypeConverter<DisplaySnapshotPtr, ui::DisplaySnapshot_Params>::Convert(
out->native_mode = DisplayMode::From<ui::DisplayMode_Params>(in.native_mode);
out->product_id = in.product_id;
out->string_representation = in.string_representation;
return out.Pass();
return out;
}
} // namespace mojo

View File

@ -198,7 +198,7 @@ SurfaceIdPtr TypeConverter<SurfaceIdPtr, cc::SurfaceId>::Convert(
SurfaceIdPtr id(SurfaceId::New());
id->local = static_cast<uint32_t>(input.id);
id->id_namespace = cc::SurfaceIdAllocator::NamespaceForId(input);
return id.Pass();
return id;
}
// static
@ -214,7 +214,7 @@ cc::SurfaceId TypeConverter<cc::SurfaceId, SurfaceIdPtr>::Convert(
ColorPtr TypeConverter<ColorPtr, SkColor>::Convert(const SkColor& input) {
ColorPtr color(Color::New());
color->rgba = input;
return color.Pass();
return color;
}
// static
@ -228,7 +228,7 @@ RenderPassIdPtr TypeConverter<RenderPassIdPtr, cc::RenderPassId>::Convert(
RenderPassIdPtr pass_id(RenderPassId::New());
pass_id->layer_id = input.layer_id;
pass_id->index = input.index;
return pass_id.Pass();
return pass_id;
}
// static
@ -337,7 +337,7 @@ QuadPtr TypeConverter<QuadPtr, cc::DrawQuad>::Convert(
default:
NOTREACHED() << "Unsupported material " << input.material;
}
return quad.Pass();
return quad;
}
// static
@ -354,7 +354,7 @@ TypeConverter<SharedQuadStatePtr, cc::SharedQuadState>::Convert(
state->opacity = input.opacity;
state->blend_mode = static_cast<SkXfermode>(input.blend_mode);
state->sorting_context_id = input.sorting_context_id;
return state.Pass();
return state;
}
// static
@ -391,7 +391,7 @@ PassPtr TypeConverter<PassPtr, cc::RenderPass>::Convert(
DCHECK_EQ(next_sqs_iter.index(), shared_quad_state.size());
pass->quads = quads.Pass();
pass->shared_quad_states = shared_quad_state.Pass();
return pass.Pass();
return pass;
}
// static
@ -416,9 +416,9 @@ TypeConverter<scoped_ptr<cc::RenderPass>, PassPtr>::Convert(
++sqs_iter;
}
if (!ConvertDrawQuad(quad, *sqs_iter, pass.get()))
return scoped_ptr<cc::RenderPass>();
return nullptr;
}
return pass.Pass();
return pass;
}
// static
@ -430,7 +430,7 @@ MailboxPtr TypeConverter<MailboxPtr, gpu::Mailbox>::Convert(
}
MailboxPtr mailbox(Mailbox::New());
mailbox->name = name.Pass();
return mailbox.Pass();
return mailbox;
}
// static
@ -449,7 +449,7 @@ MailboxHolderPtr TypeConverter<MailboxHolderPtr, gpu::MailboxHolder>::Convert(
holder->mailbox = Mailbox::From<gpu::Mailbox>(input.mailbox);
holder->texture_target = input.texture_target;
holder->sync_point = input.sync_point;
return holder.Pass();
return holder;
}
// static
@ -474,7 +474,7 @@ TypeConverter<TransferableResourcePtr, cc::TransferableResource>::Convert(
transferable->mailbox_holder = MailboxHolder::From(input.mailbox_holder);
transferable->is_repeated = input.is_repeated;
transferable->is_software = input.is_software;
return transferable.Pass();
return transferable;
}
// static
@ -501,7 +501,7 @@ Array<TransferableResourcePtr> TypeConverter<
for (size_t i = 0; i < input.size(); ++i) {
resources[i] = TransferableResource::From(input[i]);
}
return resources.Pass();
return resources;
}
// static
@ -524,7 +524,7 @@ TypeConverter<ReturnedResourcePtr, cc::ReturnedResource>::Convert(
returned->sync_point = input.sync_point;
returned->count = input.count;
returned->lost = input.lost;
return returned.Pass();
return returned;
}
// static
@ -547,7 +547,7 @@ TypeConverter<Array<ReturnedResourcePtr>, cc::ReturnedResourceArray>::Convert(
for (size_t i = 0; i < input.size(); ++i) {
resources[i] = ReturnedResource::From(input[i]);
}
return resources.Pass();
return resources;
}
// static
@ -563,7 +563,7 @@ FramePtr TypeConverter<FramePtr, cc::CompositorFrame>::Convert(
for (size_t i = 0; i < pass_list.size(); ++i) {
frame->passes[i] = Pass::From(*pass_list[i]);
}
return frame.Pass();
return frame;
}
// static
@ -584,7 +584,7 @@ TypeConverter<scoped_ptr<cc::CompositorFrame>, FramePtr>::Convert(
}
scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
frame->delegated_frame_data = frame_data.Pass();
return frame.Pass();
return frame;
}
} // namespace mojo

View File

@ -26,8 +26,6 @@ mojo_edk_source_set("embedder") {
"test_embedder.h",
]
defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ]
mojo_edk_configs = [ "mojo/edk/system:system_config" ]
public_deps = [
@ -51,17 +49,13 @@ mojo_edk_source_set("platform") {
# mojo_system_impl component.
visibility = [ ":embedder" ]
mojo_edk_visibility = [
"mojo/edk/system",
"mojo/edk/system:test_utils",
]
mojo_edk_visibility = [ "mojo/edk/system/*" ]
sources = [
"platform_channel_pair.cc",
"platform_channel_pair.h",
"platform_channel_pair_posix.cc",
"platform_channel_utils_posix.cc",
"platform_channel_utils_posix.h",
"platform_channel_utils.cc",
"platform_channel_utils.h",
"platform_handle.cc",
"platform_handle.h",
"platform_handle_utils.h",
@ -75,8 +69,6 @@ mojo_edk_source_set("platform") {
"scoped_platform_handle.h",
"simple_platform_shared_buffer.cc",
"simple_platform_shared_buffer.h",
"simple_platform_shared_buffer_android.cc",
"simple_platform_shared_buffer_posix.cc",
"simple_platform_support.cc",
"simple_platform_support.h",
]
@ -116,26 +108,25 @@ mojo_edk_source_set("delegates") {
mojo_sdk_public_deps = [ "mojo/public/cpp/system" ]
}
mojo_edk_source_set("embedder_unittests") {
mojo_edk_source_set("unittests") {
testonly = true
mojo_edk_visibility = [ "mojo/edk/system:mojo_system_unittests" ]
sources = [
"embedder_unittest.cc",
"platform_channel_pair_posix_unittest.cc",
"platform_channel_pair_unittest.cc",
"simple_platform_shared_buffer_unittest.cc",
]
deps = [
"//base",
"//base/test:test_support",
"//testing/gtest",
]
mojo_edk_deps = [
"mojo/edk/test:test_support",
"mojo/edk/system",
"mojo/edk/system:test_utils",
"mojo/edk/system/test",
"mojo/edk/util",
]
}

View File

@ -25,7 +25,9 @@
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/platform_handle_dispatcher.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
using mojo::util::RefPtr;
namespace mojo {
namespace embedder {
@ -134,8 +136,7 @@ MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle,
*platform_handle =
static_cast<system::PlatformHandleDispatcher*>(dispatcher.get())
->PassPlatformHandle()
.Pass();
->PassPlatformHandle();
return MOJO_RESULT_OK;
}
@ -185,7 +186,7 @@ ScopedMessagePipeHandle ConnectToSlave(
internal::g_ipc_support->GenerateConnectionIdentifier();
*platform_connection_id = connection_id.ToString();
system::ChannelId channel_id = system::kInvalidChannelId;
system::RefPtr<system::MessagePipeDispatcher> dispatcher =
RefPtr<system::MessagePipeDispatcher> dispatcher =
internal::g_ipc_support->ConnectToSlave(
connection_id, slave_info, platform_handle.Pass(),
did_connect_to_slave_callback, std::move(did_connect_to_slave_runner),
@ -212,7 +213,7 @@ ScopedMessagePipeHandle ConnectToMaster(
CHECK(ok);
system::ChannelId channel_id = system::kInvalidChannelId;
system::RefPtr<system::MessagePipeDispatcher> dispatcher =
RefPtr<system::MessagePipeDispatcher> dispatcher =
internal::g_ipc_support->ConnectToMaster(
connection_id, did_connect_to_master_callback,
std::move(did_connect_to_master_runner), &channel_id);
@ -236,7 +237,7 @@ ScopedMessagePipeHandle CreateChannelOnIOThread(
internal::g_ipc_support->channel_manager();
*channel_info = new ChannelInfo(MakeChannelId());
system::RefPtr<system::MessagePipeDispatcher> dispatcher =
RefPtr<system::MessagePipeDispatcher> dispatcher =
channel_manager->CreateChannelOnIOThread((*channel_info)->channel_id,
platform_handle.Pass());
@ -259,7 +260,7 @@ ScopedMessagePipeHandle CreateChannel(
system::ChannelId channel_id = MakeChannelId();
std::unique_ptr<ChannelInfo> channel_info(new ChannelInfo(channel_id));
system::RefPtr<system::MessagePipeDispatcher> dispatcher =
RefPtr<system::MessagePipeDispatcher> dispatcher =
channel_manager->CreateChannel(
channel_id, platform_handle.Pass(),
base::Bind(did_create_channel_callback,

View File

@ -9,7 +9,6 @@
#include <string>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/task_runner.h"
#include "mojo/edk/embedder/channel_info_forward.h"
#include "mojo/edk/embedder/platform_task_runner.h"
@ -101,7 +100,7 @@ void InitIPCSupport(ProcessType process_type,
void ShutdownIPCSupportOnIOThread();
// Like |ShutdownIPCSupportOnIOThread()|, but may be called from any thread,
// signalling shutdown completion via the process delegate's
// signaling shutdown completion via the process delegate's
// |OnShutdownComplete()|.
void ShutdownIPCSupport();

View File

@ -9,28 +9,30 @@
#include <memory>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/test_embedder.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/test_command_line.h"
#include "mojo/edk/system/test/test_io_thread.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/test/multiprocess_test_helper.h"
#include "mojo/edk/test/scoped_ipc_support.h"
#include "mojo/edk/test/test_io_thread.h"
#include "mojo/edk/util/command_line.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/core.h"
#include "mojo/public/cpp/system/handle.h"
#include "mojo/public/cpp/system/macros.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::system::test::TestIOThread;
using mojo::util::Mutex;
using mojo::util::MutexLocker;
namespace mojo {
using test::TestIOThread;
namespace embedder {
namespace {
@ -55,7 +57,6 @@ class ScopedTestChannel {
// object is alive).
explicit ScopedTestChannel(ScopedPlatformHandle platform_handle)
: bootstrap_message_pipe_(MOJO_HANDLE_INVALID),
event_(true, false), // Manual reset.
channel_info_(nullptr),
wait_on_shutdown_(true) {
bootstrap_message_pipe_ =
@ -72,7 +73,7 @@ class ScopedTestChannel {
// the I/O thread must be alive and pumping messages.)
~ScopedTestChannel() {
// |WaitForChannelCreationCompletion()| must be called before destruction.
CHECK(event_.IsSignaled());
CHECK(event_.IsSignaledForTest());
event_.Reset();
if (wait_on_shutdown_) {
DestroyChannel(channel_info_,
@ -117,7 +118,7 @@ class ScopedTestChannel {
// Set after channel creation has been completed (i.e., the callback to
// |CreateChannel()| has been called). Also used in the destructor to wait for
// |DestroyChannel()| completion.
base::WaitableEvent event_;
mojo::system::ManualResetWaitableEvent event_;
// Valid after channel creation completion until destruction.
ChannelInfo* channel_info_;
@ -196,25 +197,27 @@ TEST_F(EmbedderTest, ChannelsBasic) {
class TestAsyncWaiter {
public:
TestAsyncWaiter() : event_(true, false), wait_result_(MOJO_RESULT_UNKNOWN) {}
TestAsyncWaiter() : wait_result_(MOJO_RESULT_UNKNOWN) {}
void Awake(MojoResult result) {
system::MutexLocker l(&wait_result_mutex_);
MutexLocker l(&wait_result_mutex_);
wait_result_ = result;
event_.Signal();
}
bool TryWait() { return event_.TimedWait(TestTimeouts::action_timeout()); }
bool TryWait() {
return !event_.WaitWithTimeout(mojo::system::test::ActionTimeout());
}
MojoResult wait_result() const {
system::MutexLocker l(&wait_result_mutex_);
MutexLocker l(&wait_result_mutex_);
return wait_result_;
}
private:
base::WaitableEvent event_;
mojo::system::ManualResetWaitableEvent event_;
mutable system::Mutex wait_result_mutex_;
mutable Mutex wait_result_mutex_;
MojoResult wait_result_ MOJO_GUARDED_BY(wait_result_mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(TestAsyncWaiter);
@ -406,11 +409,12 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessMasterSlave) {
mojo::test::MultiprocessTestHelper multiprocess_test_helper;
std::string connection_id;
base::WaitableEvent event(true, false);
mojo::system::ManualResetWaitableEvent event;
ChannelInfo* channel_info = nullptr;
ScopedMessagePipeHandle mp = ConnectToSlave(
nullptr, multiprocess_test_helper.server_platform_handle.Pass(),
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)),
base::Bind(&mojo::system::ManualResetWaitableEvent::Signal,
base::Unretained(&event)),
nullptr, &connection_id, &channel_info);
ASSERT_TRUE(mp.is_valid());
EXPECT_TRUE(channel_info);
@ -424,9 +428,8 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessMasterSlave) {
MOJO_WRITE_MESSAGE_FLAG_NONE));
// Wait for a response.
EXPECT_EQ(MOJO_RESULT_OK,
Wait(mp.get(), MOJO_HANDLE_SIGNAL_READABLE,
mojo::system::test::ActionDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, Wait(mp.get(), MOJO_HANDLE_SIGNAL_READABLE,
mojo::system::test::ActionTimeout(), nullptr));
// The response message should say "world".
char buffer[100];
@ -441,7 +444,7 @@ TEST_F(EmbedderTest, MAYBE_MultiprocessMasterSlave) {
EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
EXPECT_FALSE(event.WaitWithTimeout(mojo::system::test::ActionTimeout()));
test_io_thread().PostTaskAndWait(
base::Bind(&DestroyChannelOnIOThread, base::Unretained(channel_info)));
}
@ -480,17 +483,16 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlave) {
mojo::test::ScopedSlaveIPCSupport ipc_support(
test_io_thread.task_runner(), client_platform_handle.Pass());
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag));
std::string connection_id =
command_line.GetSwitchValueASCII(kConnectionIdFlag);
std::string connection_id;
ASSERT_TRUE(mojo::system::test::GetTestCommandLine()->GetOptionValue(
kConnectionIdFlag, &connection_id));
ASSERT_FALSE(connection_id.empty());
base::WaitableEvent event(true, false);
mojo::system::ManualResetWaitableEvent event;
ChannelInfo* channel_info = nullptr;
ScopedMessagePipeHandle mp = ConnectToMaster(
connection_id,
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event)),
base::Bind(&mojo::system::ManualResetWaitableEvent::Signal,
base::Unretained(&event)),
nullptr, &channel_info);
ASSERT_TRUE(mp.is_valid());
EXPECT_TRUE(channel_info);
@ -498,7 +500,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlave) {
// Wait for the master to send us a message.
EXPECT_EQ(MOJO_RESULT_OK,
Wait(mp.get(), MOJO_HANDLE_SIGNAL_READABLE,
mojo::system::test::ActionDeadline(), nullptr));
mojo::system::test::ActionTimeout(), nullptr));
// It should say "hello".
char buffer[100];
@ -515,7 +517,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlave) {
mp.reset();
EXPECT_TRUE(event.TimedWait(TestTimeouts::action_timeout()));
EXPECT_FALSE(event.WaitWithTimeout(mojo::system::test::ActionTimeout()));
test_io_thread.PostTaskAndWait(
base::Bind(&DestroyChannelOnIOThread, base::Unretained(channel_info)));
}

View File

@ -4,14 +4,63 @@
#include "mojo/edk/embedder/platform_channel_pair.h"
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_handle.h"
namespace mojo {
namespace embedder {
namespace {
bool IsTargetDescriptorUsed(
const base::FileHandleMappingVector& file_handle_mapping,
int target_fd) {
for (size_t i = 0; i < file_handle_mapping.size(); i++) {
if (file_handle_mapping[i].second == target_fd)
return true;
}
return false;
}
} // namespace
const char PlatformChannelPair::kMojoPlatformChannelHandleSwitch[] =
"mojo-platform-channel-handle";
PlatformChannelPair::PlatformChannelPair() {
// Create the Unix domain socket and set the ends to nonblocking.
int fds[2];
// TODO(vtl): Maybe fail gracefully if |socketpair()| fails.
PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
#if defined(OS_MACOSX)
// This turns off |SIGPIPE| when writing to a closed socket (causing it to
// fail with |EPIPE| instead). On Linux, we have to use |send...()| with
// |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
int no_sigpipe = 1;
PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
sizeof(no_sigpipe)) == 0);
PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
sizeof(no_sigpipe)) == 0);
#endif // defined(OS_MACOSX)
server_handle_.reset(PlatformHandle(fds[0]));
DCHECK(server_handle_.is_valid());
client_handle_.reset(PlatformHandle(fds[1]));
DCHECK(client_handle_.is_valid());
}
PlatformChannelPair::~PlatformChannelPair() {
}
@ -23,6 +72,55 @@ ScopedPlatformHandle PlatformChannelPair::PassClientHandle() {
return client_handle_.Pass();
}
// static
ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess(
const base::CommandLine& command_line) {
std::string client_fd_string =
command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
int client_fd = -1;
if (client_fd_string.empty() ||
!base::StringToInt(client_fd_string, &client_fd) ||
client_fd < base::GlobalDescriptors::kBaseDescriptor) {
LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
return ScopedPlatformHandle();
}
return ScopedPlatformHandle(PlatformHandle(client_fd));
}
void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
base::CommandLine* command_line,
base::FileHandleMappingVector* handle_passing_info) const {
DCHECK(command_line);
DCHECK(handle_passing_info);
// This is an arbitrary sanity check. (Note that this guarantees that the loop
// below will terminate sanely.)
CHECK_LT(handle_passing_info->size(), 1000u);
DCHECK(client_handle_.is_valid());
// Find a suitable FD to map our client handle to in the child process.
// This has quadratic time complexity in the size of |*handle_passing_info|,
// but |*handle_passing_info| should be very small (usually/often empty).
int target_fd = base::GlobalDescriptors::kBaseDescriptor;
while (IsTargetDescriptorUsed(*handle_passing_info, target_fd))
target_fd++;
handle_passing_info->push_back(
std::pair<int, int>(client_handle_.get().fd, target_fd));
// Log a warning if the command line already has the switch, but "clobber" it
// anyway, since it's reasonably likely that all the switches were just copied
// from the parent.
LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch))
<< "Child command line already has switch --"
<< kMojoPlatformChannelHandleSwitch << "="
<< command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
// (Any existing switch won't actually be removed from the command line, but
// the last one appended takes precedence.)
command_line->AppendSwitchASCII(kMojoPlatformChannelHandleSwitch,
base::IntToString(target_fd));
}
void PlatformChannelPair::ChildProcessLaunched() {
DCHECK(client_handle_.is_valid());
client_handle_.reset();

View File

@ -37,9 +37,9 @@ using HandlePassingInformation = base::FileHandleMappingVector;
// implementations.
//
// Note: On POSIX platforms, to write to the "pipe", use
// |PlatformChannel{Write,Writev}()| (from platform_channel_utils_posix.h)
// instead of |write()|, |writev()|, etc. Otherwise, you have to worry about
// platform differences in suppressing |SIGPIPE|.
// |PlatformChannel{Write,Writev}()| (from platform_channel_utils.h) instead of
// |write()|, |writev()|, etc. Otherwise, you have to worry about platform
// differences in suppressing |SIGPIPE|.
class PlatformChannelPair {
public:
PlatformChannelPair();

View File

@ -1,111 +0,0 @@
// Copyright 2014 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/edk/embedder/platform_channel_pair.h"
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "base/command_line.h"
#include "base/logging.h"
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_handle.h"
namespace mojo {
namespace embedder {
namespace {
bool IsTargetDescriptorUsed(
const base::FileHandleMappingVector& file_handle_mapping,
int target_fd) {
for (size_t i = 0; i < file_handle_mapping.size(); i++) {
if (file_handle_mapping[i].second == target_fd)
return true;
}
return false;
}
} // namespace
PlatformChannelPair::PlatformChannelPair() {
// Create the Unix domain socket and set the ends to nonblocking.
int fds[2];
// TODO(vtl): Maybe fail gracefully if |socketpair()| fails.
PCHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == 0);
PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
#if defined(OS_MACOSX)
// This turns off |SIGPIPE| when writing to a closed socket (causing it to
// fail with |EPIPE| instead). On Linux, we have to use |send...()| with
// |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
int no_sigpipe = 1;
PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
sizeof(no_sigpipe)) == 0);
PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
sizeof(no_sigpipe)) == 0);
#endif // defined(OS_MACOSX)
server_handle_.reset(PlatformHandle(fds[0]));
DCHECK(server_handle_.is_valid());
client_handle_.reset(PlatformHandle(fds[1]));
DCHECK(client_handle_.is_valid());
}
// static
ScopedPlatformHandle PlatformChannelPair::PassClientHandleFromParentProcess(
const base::CommandLine& command_line) {
std::string client_fd_string =
command_line.GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
int client_fd = -1;
if (client_fd_string.empty() ||
!base::StringToInt(client_fd_string, &client_fd) ||
client_fd < base::GlobalDescriptors::kBaseDescriptor) {
LOG(ERROR) << "Missing or invalid --" << kMojoPlatformChannelHandleSwitch;
return ScopedPlatformHandle();
}
return ScopedPlatformHandle(PlatformHandle(client_fd));
}
void PlatformChannelPair::PrepareToPassClientHandleToChildProcess(
base::CommandLine* command_line,
base::FileHandleMappingVector* handle_passing_info) const {
DCHECK(command_line);
DCHECK(handle_passing_info);
// This is an arbitrary sanity check. (Note that this guarantees that the loop
// below will terminate sanely.)
CHECK_LT(handle_passing_info->size(), 1000u);
DCHECK(client_handle_.is_valid());
// Find a suitable FD to map our client handle to in the child process.
// This has quadratic time complexity in the size of |*handle_passing_info|,
// but |*handle_passing_info| should be very small (usually/often empty).
int target_fd = base::GlobalDescriptors::kBaseDescriptor;
while (IsTargetDescriptorUsed(*handle_passing_info, target_fd))
target_fd++;
handle_passing_info->push_back(
std::pair<int, int>(client_handle_.get().fd, target_fd));
// Log a warning if the command line already has the switch, but "clobber" it
// anyway, since it's reasonably likely that all the switches were just copied
// from the parent.
LOG_IF(WARNING, command_line->HasSwitch(kMojoPlatformChannelHandleSwitch))
<< "Child command line already has switch --"
<< kMojoPlatformChannelHandleSwitch << "="
<< command_line->GetSwitchValueASCII(kMojoPlatformChannelHandleSwitch);
// (Any existing switch won't actually be removed from the command line, but
// the last one appended takes precedence.)
command_line->AppendSwitchASCII(kMojoPlatformChannelHandleSwitch,
base::IntToString(target_fd));
}
} // namespace embedder
} // namespace mojo

View File

@ -14,14 +14,15 @@
#include <unistd.h>
#include <deque>
#include <utility>
#include "base/logging.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_channel_utils.h"
#include "mojo/edk/embedder/platform_handle.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/test/scoped_test_dir.h"
#include "mojo/edk/system/test/scoped_test_dir.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/edk/util/scoped_file.h"
#include "mojo/public/cpp/system/macros.h"
@ -38,10 +39,10 @@ void WaitReadable(PlatformHandle h) {
CHECK_EQ(poll(&pfds, 1, -1), 1);
}
class PlatformChannelPairPosixTest : public testing::Test {
class PlatformChannelPairTest : public testing::Test {
public:
PlatformChannelPairPosixTest() {}
~PlatformChannelPairPosixTest() override {}
PlatformChannelPairTest() {}
~PlatformChannelPairTest() override {}
void SetUp() override {
// Make sure |SIGPIPE| isn't being ignored.
@ -58,13 +59,13 @@ class PlatformChannelPairPosixTest : public testing::Test {
private:
struct sigaction old_action_;
MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest);
MOJO_DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairTest);
};
TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
TEST_F(PlatformChannelPairTest, NoSigPipe) {
PlatformChannelPair channel_pair;
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle();
// Write to the client.
static const char kHello[] = "hello";
@ -102,10 +103,10 @@ TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
PLOG(WARNING) << "write (expected EPIPE)";
}
TEST_F(PlatformChannelPairPosixTest, SendReceiveData) {
TEST_F(PlatformChannelPairTest, SendReceiveData) {
PlatformChannelPair channel_pair;
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle();
for (size_t i = 0; i < 10; i++) {
std::string send_string(1 << i, 'A' + i);
@ -126,14 +127,14 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveData) {
}
}
TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
mojo::test::ScopedTestDir test_dir;
TEST_F(PlatformChannelPairTest, SendReceiveFDs) {
mojo::system::test::ScopedTestDir test_dir;
static const char kHello[] = "hello";
PlatformChannelPair channel_pair;
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle();
// Reduce the number of FDs opened on OS X to avoid test flake.
#if defined(OS_MACOSX)
@ -152,7 +153,7 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
ASSERT_TRUE(fp);
ASSERT_EQ(j, fwrite(std::string(j, c).data(), 1, j, fp.get()));
platform_handles->push_back(
test::PlatformHandleFromFILE(fp.Pass()).release());
test::PlatformHandleFromFILE(std::move(fp)).release());
ASSERT_TRUE(platform_handles->back().is_valid());
}
@ -189,14 +190,14 @@ TEST_F(PlatformChannelPairPosixTest, SendReceiveFDs) {
}
}
TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
mojo::test::ScopedTestDir test_dir;
TEST_F(PlatformChannelPairTest, AppendReceivedFDs) {
mojo::system::test::ScopedTestDir test_dir;
static const char kHello[] = "hello";
PlatformChannelPair channel_pair;
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
ScopedPlatformHandle server_handle = channel_pair.PassServerHandle();
ScopedPlatformHandle client_handle = channel_pair.PassClientHandle();
const std::string file_contents("hello world");
@ -207,7 +208,7 @@ TEST_F(PlatformChannelPairPosixTest, AppendReceivedFDs) {
fwrite(file_contents.data(), 1, file_contents.size(), fp.get()));
ScopedPlatformHandleVectorPtr platform_handles(new PlatformHandleVector);
platform_handles->push_back(
test::PlatformHandleFromFILE(fp.Pass()).release());
test::PlatformHandleFromFILE(std::move(fp)).release());
ASSERT_TRUE(platform_handles->back().is_valid());
// Send the FD (+ "hello").

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/edk/embedder/platform_channel_utils_posix.h"
#include "mojo/edk/embedder/platform_channel_utils.h"
#include <sys/socket.h>
#include <sys/uio.h>

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
#ifndef MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_H_
#define MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_H_
#include <stddef.h>
#include <sys/types.h> // For |ssize_t|.
@ -71,4 +71,4 @@ ssize_t PlatformChannelRecvmsg(PlatformHandle h,
} // namespace embedder
} // namespace mojo
#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_POSIX_H_
#endif // MOJO_EDK_EMBEDDER_PLATFORM_CHANNEL_UTILS_H_

View File

@ -9,8 +9,8 @@
#include <memory>
#include "base/memory/ref_counted.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/util/ref_counted.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -34,7 +34,7 @@ class PlatformSharedBufferMapping;
//
// TODO(vtl): Rectify this with |base::SharedMemory|.
class PlatformSharedBuffer
: public base::RefCountedThreadSafe<PlatformSharedBuffer> {
: public util::RefCountedThreadSafe<PlatformSharedBuffer> {
public:
// Gets the size of shared buffer (in number of bytes).
virtual size_t GetNumBytes() const = 0;
@ -65,7 +65,7 @@ class PlatformSharedBuffer
virtual ScopedPlatformHandle PassPlatformHandle() = 0;
protected:
friend class base::RefCountedThreadSafe<PlatformSharedBuffer>;
friend class util::RefCountedThreadSafe<PlatformSharedBuffer>;
PlatformSharedBuffer() {}
virtual ~PlatformSharedBuffer() {}

View File

@ -8,6 +8,7 @@
#include <stddef.h>
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
@ -42,8 +43,9 @@ class PlatformSupport {
// Gets cryptographically-secure (pseudo)random bytes.
virtual void GetCryptoRandomBytes(void* bytes, size_t num_bytes) = 0;
virtual PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) = 0;
virtual PlatformSharedBuffer* CreateSharedBufferFromHandle(
virtual util::RefPtr<PlatformSharedBuffer> CreateSharedBuffer(
size_t num_bytes) = 0;
virtual util::RefPtr<PlatformSharedBuffer> CreateSharedBufferFromHandle(
size_t num_bytes,
ScopedPlatformHandle platform_handle) = 0;

View File

@ -4,44 +4,62 @@
#include "mojo/edk/embedder/simple_platform_shared_buffer.h"
#include <stdint.h>
#include <stdio.h> // For |fileno()|.
#include <sys/mman.h> // For |mmap()|/|munmap()|.
#include <sys/stat.h>
#include <sys/types.h> // For |off_t|.
#include <unistd.h>
#include <limits>
#include <utility>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sys_info.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "mojo/edk/embedder/platform_handle_utils.h"
#include "mojo/edk/util/scoped_file.h"
#if defined(OS_ANDROID)
#include "third_party/ashmem/ashmem.h"
#endif // defined(OS_ANDROID)
using mojo::util::RefPtr;
// We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
// |uint64_t|.
static_assert(sizeof(size_t) <= sizeof(uint64_t), "size_t too big");
static_assert(sizeof(off_t) <= sizeof(uint64_t), "off_t too big");
namespace mojo {
namespace embedder {
// SimplePlatformSharedBuffer --------------------------------------------------
// static
SimplePlatformSharedBuffer* SimplePlatformSharedBuffer::Create(
RefPtr<SimplePlatformSharedBuffer> SimplePlatformSharedBuffer::Create(
size_t num_bytes) {
DCHECK_GT(num_bytes, 0u);
SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes);
if (!rv->Init()) {
// We can't just delete it directly, due to the "in destructor" (debug)
// check.
scoped_refptr<SimplePlatformSharedBuffer> deleter(rv);
return nullptr;
}
return rv;
RefPtr<SimplePlatformSharedBuffer> rv(
AdoptRef(new SimplePlatformSharedBuffer(num_bytes)));
return rv->Init() ? rv : nullptr;
}
// static
SimplePlatformSharedBuffer*
RefPtr<SimplePlatformSharedBuffer>
SimplePlatformSharedBuffer::CreateFromPlatformHandle(
size_t num_bytes,
ScopedPlatformHandle platform_handle) {
DCHECK_GT(num_bytes, 0u);
SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes);
if (!rv->InitFromPlatformHandle(platform_handle.Pass())) {
// We can't just delete it directly, due to the "in destructor" (debug)
// check.
scoped_refptr<SimplePlatformSharedBuffer> deleter(rv);
return nullptr;
}
return rv;
RefPtr<SimplePlatformSharedBuffer> rv(
AdoptRef(new SimplePlatformSharedBuffer(num_bytes)));
return rv->InitFromPlatformHandle(std::move(platform_handle)) ? rv : nullptr;
}
size_t SimplePlatformSharedBuffer::GetNumBytes() const {
@ -72,7 +90,32 @@ bool SimplePlatformSharedBuffer::IsValidMap(size_t offset, size_t length) {
std::unique_ptr<PlatformSharedBufferMapping>
SimplePlatformSharedBuffer::MapNoCheck(size_t offset, size_t length) {
DCHECK(IsValidMap(offset, length));
return MapImpl(offset, length);
size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
size_t real_offset = offset - offset_rounding;
size_t real_length = length + offset_rounding;
// This should hold (since we checked |num_bytes| versus the maximum value of
// |off_t| on creation, but it never hurts to be paranoid.
DCHECK_LE(static_cast<uint64_t>(real_offset),
static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
void* real_base =
mmap(nullptr, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
handle_.get().fd, static_cast<off_t>(real_offset));
// |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
// return null either.
if (real_base == MAP_FAILED || !real_base) {
PLOG(ERROR) << "mmap";
return nullptr;
}
void* base = static_cast<char*>(real_base) + offset_rounding;
// Note: We can't use |MakeUnique| here, since it's not a friend of
// |SimplePlatformSharedBufferMapping| (only we are).
return std::unique_ptr<SimplePlatformSharedBufferMapping>(
new SimplePlatformSharedBufferMapping(base, length, real_base,
real_length));
}
ScopedPlatformHandle SimplePlatformSharedBuffer::DuplicatePlatformHandle() {
@ -81,7 +124,7 @@ ScopedPlatformHandle SimplePlatformSharedBuffer::DuplicatePlatformHandle() {
ScopedPlatformHandle SimplePlatformSharedBuffer::PassPlatformHandle() {
DCHECK(HasOneRef());
return handle_.Pass();
return std::move(handle_);
}
SimplePlatformSharedBuffer::SimplePlatformSharedBuffer(size_t num_bytes)
@ -103,5 +146,125 @@ size_t SimplePlatformSharedBufferMapping::GetLength() const {
return length_;
}
bool SimplePlatformSharedBuffer::Init() {
DCHECK(!handle_.is_valid());
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
ScopedPlatformHandle handle;
// Use ashmem on Android.
#if defined(OS_ANDROID)
handle.reset(PlatformHandle(ashmem_create_region(nullptr, num_bytes_)));
if (!handle.is_valid()) {
DPLOG(ERROR) << "ashmem_create_region()";
return false;
}
if (ashmem_set_prot_region(handle.get().fd, PROT_READ | PROT_WRITE) < 0) {
DPLOG(ERROR) << "ashmem_set_prot_region()";
return false;
}
#else
base::ThreadRestrictions::ScopedAllowIO allow_io;
// TODO(vtl): This is stupid. The implementation of
// |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
// |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
// can own. (base/memory/shared_memory_posix.cc does this too, with more
// |fstat()|s thrown in for good measure.)
base::FilePath shared_buffer_dir;
if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
LOG(ERROR) << "Failed to get temporary directory for shared memory";
return false;
}
base::FilePath shared_buffer_file;
util::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
shared_buffer_dir, &shared_buffer_file));
if (!fp) {
LOG(ERROR) << "Failed to create/open temporary file for shared memory";
return false;
}
// Note: |unlink()| is not interruptible.
if (unlink(shared_buffer_file.value().c_str()) != 0) {
PLOG(WARNING) << "unlink";
// This isn't "fatal" (e.g., someone else may have unlinked the file first),
// so we may as well continue.
}
// Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
handle.reset(PlatformHandle(dup(fileno(fp.get()))));
if (!handle.is_valid()) {
PLOG(ERROR) << "dup";
return false;
}
if (HANDLE_EINTR(
ftruncate(handle.get().fd, static_cast<off_t>(num_bytes_))) != 0) {
PLOG(ERROR) << "ftruncate";
return false;
}
#endif // defined(OS_ANDROID)
handle_ = std::move(handle);
return true;
}
bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
ScopedPlatformHandle platform_handle) {
DCHECK(!handle_.is_valid());
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
// Use ashmem on Android.
#if defined(OS_ANDROID)
int size = ashmem_get_size_region(platform_handle.get().fd);
if (size < 0) {
DPLOG(ERROR) << "ashmem_get_size_region()";
return false;
}
if (static_cast<size_t>(size) != num_bytes_) {
LOG(ERROR) << "Shared memory region has the wrong size";
return false;
}
#else
struct stat sb = {};
// Note: |fstat()| isn't interruptible.
if (fstat(platform_handle.get().fd, &sb) != 0) {
PLOG(ERROR) << "fstat";
return false;
}
if (!S_ISREG(sb.st_mode)) {
LOG(ERROR) << "Platform handle not to a regular file";
return false;
}
if (sb.st_size != static_cast<off_t>(num_bytes_)) {
LOG(ERROR) << "Shared memory file has the wrong size";
return false;
}
// TODO(vtl): More checks?
#endif // defined(OS_ANDROID)
handle_ = platform_handle.Pass();
return true;
}
// SimplePlatformSharedBufferMapping -------------------------------------------
void SimplePlatformSharedBufferMapping::Unmap() {
int result = munmap(real_base_, real_length_);
PLOG_IF(ERROR, result != 0) << "munmap";
}
} // namespace embedder
} // namespace mojo

View File

@ -8,6 +8,7 @@
#include <stddef.h>
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -18,9 +19,9 @@ class SimplePlatformSharedBuffer final : public PlatformSharedBuffer {
public:
// Creates a shared buffer of size |num_bytes| bytes (initially zero-filled).
// |num_bytes| must be nonzero. Returns null on failure.
static SimplePlatformSharedBuffer* Create(size_t num_bytes);
static util::RefPtr<SimplePlatformSharedBuffer> Create(size_t num_bytes);
static SimplePlatformSharedBuffer* CreateFromPlatformHandle(
static util::RefPtr<SimplePlatformSharedBuffer> CreateFromPlatformHandle(
size_t num_bytes,
ScopedPlatformHandle platform_handle);
@ -39,8 +40,6 @@ class SimplePlatformSharedBuffer final : public PlatformSharedBuffer {
explicit SimplePlatformSharedBuffer(size_t num_bytes);
~SimplePlatformSharedBuffer() override;
// Implemented in simple_platform_shared_buffer_{posix,win}.cc:
// This is called by |Create()| before this object is given to anyone.
bool Init();
@ -49,10 +48,6 @@ class SimplePlatformSharedBuffer final : public PlatformSharedBuffer {
// claimed |num_bytes_|.)
bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle);
// The platform-dependent part of |Map()|; doesn't check arguments.
std::unique_ptr<PlatformSharedBufferMapping> MapImpl(size_t offset,
size_t length);
const size_t num_bytes_;
// This is set in |Init()|/|InitFromPlatformHandle()| and never modified

View File

@ -1,71 +0,0 @@
// Copyright 2014 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/edk/embedder/simple_platform_shared_buffer.h"
#include <stdint.h>
#include <sys/mman.h> // For |PROT_...|.
#include <sys/types.h> // For |off_t|.
#include <limits>
#include "base/logging.h"
#include "third_party/ashmem/ashmem.h"
namespace mojo {
namespace embedder {
// SimplePlatformSharedBuffer --------------------------------------------------
bool SimplePlatformSharedBuffer::Init() {
DCHECK(!handle_.is_valid());
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
ScopedPlatformHandle handle(
PlatformHandle(ashmem_create_region(nullptr, num_bytes_)));
if (!handle.is_valid()) {
DPLOG(ERROR) << "ashmem_create_region()";
return false;
}
if (ashmem_set_prot_region(handle.get().fd, PROT_READ | PROT_WRITE) < 0) {
DPLOG(ERROR) << "ashmem_set_prot_region()";
return false;
}
handle_ = handle.Pass();
return true;
}
bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
ScopedPlatformHandle platform_handle) {
DCHECK(!handle_.is_valid());
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
int size = ashmem_get_size_region(platform_handle.get().fd);
if (size < 0) {
DPLOG(ERROR) << "ashmem_get_size_region()";
return false;
}
if (static_cast<size_t>(size) != num_bytes_) {
LOG(ERROR) << "Shared memory region has the wrong size";
return false;
}
handle_ = platform_handle.Pass();
return true;
}
} // namespace embedder
} // namespace mojo

View File

@ -1,160 +0,0 @@
// Copyright 2014 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/edk/embedder/simple_platform_shared_buffer.h"
#include <stdint.h>
#include <stdio.h> // For |fileno()|.
#include <sys/mman.h> // For |mmap()|/|munmap()|.
#include <sys/stat.h>
#include <sys/types.h> // For |off_t|.
#include <unistd.h>
#include <limits>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sys_info.h"
#include "base/threading/thread_restrictions.h"
#include "mojo/edk/util/scoped_file.h"
// We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
// |uint64_t|.
static_assert(sizeof(size_t) <= sizeof(uint64_t), "size_t too big");
static_assert(sizeof(off_t) <= sizeof(uint64_t), "off_t too big");
namespace mojo {
namespace embedder {
// SimplePlatformSharedBuffer --------------------------------------------------
// The implementation for android uses ashmem to generate the file descriptor
// for the shared memory. See simple_platform_shared_buffer_android.cc
#if !defined(OS_ANDROID)
bool SimplePlatformSharedBuffer::Init() {
DCHECK(!handle_.is_valid());
base::ThreadRestrictions::ScopedAllowIO allow_io;
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
// TODO(vtl): This is stupid. The implementation of
// |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
// |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
// can own. (base/memory/shared_memory_posix.cc does this too, with more
// |fstat()|s thrown in for good measure.)
base::FilePath shared_buffer_dir;
if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
LOG(ERROR) << "Failed to get temporary directory for shared memory";
return false;
}
base::FilePath shared_buffer_file;
util::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
shared_buffer_dir, &shared_buffer_file));
if (!fp) {
LOG(ERROR) << "Failed to create/open temporary file for shared memory";
return false;
}
// Note: |unlink()| is not interruptible.
if (unlink(shared_buffer_file.value().c_str()) != 0) {
PLOG(WARNING) << "unlink";
// This isn't "fatal" (e.g., someone else may have unlinked the file first),
// so we may as well continue.
}
// Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
ScopedPlatformHandle handle(PlatformHandle(dup(fileno(fp.get()))));
if (!handle.is_valid()) {
PLOG(ERROR) << "dup";
return false;
}
if (HANDLE_EINTR(
ftruncate(handle.get().fd, static_cast<off_t>(num_bytes_))) != 0) {
PLOG(ERROR) << "ftruncate";
return false;
}
handle_ = handle.Pass();
return true;
}
bool SimplePlatformSharedBuffer::InitFromPlatformHandle(
ScopedPlatformHandle platform_handle) {
DCHECK(!handle_.is_valid());
if (static_cast<uint64_t>(num_bytes_) >
static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
return false;
}
struct stat sb = {};
// Note: |fstat()| isn't interruptible.
if (fstat(platform_handle.get().fd, &sb) != 0) {
PLOG(ERROR) << "fstat";
return false;
}
if (!S_ISREG(sb.st_mode)) {
LOG(ERROR) << "Platform handle not to a regular file";
return false;
}
if (sb.st_size != static_cast<off_t>(num_bytes_)) {
LOG(ERROR) << "Shared memory file has the wrong size";
return false;
}
// TODO(vtl): More checks?
handle_ = platform_handle.Pass();
return true;
}
#endif // !defined(OS_ANDROID)
std::unique_ptr<PlatformSharedBufferMapping>
SimplePlatformSharedBuffer::MapImpl(size_t offset, size_t length) {
size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
size_t real_offset = offset - offset_rounding;
size_t real_length = length + offset_rounding;
// This should hold (since we checked |num_bytes| versus the maximum value of
// |off_t| on creation, but it never hurts to be paranoid.
DCHECK_LE(static_cast<uint64_t>(real_offset),
static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
void* real_base =
mmap(nullptr, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
handle_.get().fd, static_cast<off_t>(real_offset));
// |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
// return null either.
if (real_base == MAP_FAILED || !real_base) {
PLOG(ERROR) << "mmap";
return nullptr;
}
void* base = static_cast<char*>(real_base) + offset_rounding;
// Note: We can't use |MakeUnique| here, since it's not a friend of
// |SimplePlatformSharedBufferMapping| (only we are).
return std::unique_ptr<SimplePlatformSharedBufferMapping>(
new SimplePlatformSharedBufferMapping(base, length, real_base,
real_length));
}
// SimplePlatformSharedBufferMapping -------------------------------------------
void SimplePlatformSharedBufferMapping::Unmap() {
int result = munmap(real_base_, real_length_);
PLOG_IF(ERROR, result != 0) << "munmap";
}
} // namespace embedder
} // namespace mojo

View File

@ -6,7 +6,6 @@
#include <limits>
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -21,8 +20,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) {
const int kFudge = 1234567890;
// Make some memory.
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(kNumBytes));
auto buffer = SimplePlatformSharedBuffer::Create(kNumBytes);
ASSERT_TRUE(buffer);
// Map it all, scribble some stuff, and then unmap it.
@ -98,8 +96,7 @@ TEST(SimplePlatformSharedBufferTest, Basic) {
// TODO(vtl): Bigger buffers.
TEST(SimplePlatformSharedBufferTest, InvalidMappings) {
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(100));
auto buffer = SimplePlatformSharedBuffer::Create(100);
ASSERT_TRUE(buffer);
// Zero length not allowed.
@ -129,8 +126,7 @@ TEST(SimplePlatformSharedBufferTest, TooBig) {
// If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds
// (since it only involves creating a 4 GB file).
const size_t kMaxSizeT = std::numeric_limits<size_t>::max();
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(kMaxSizeT));
auto buffer = SimplePlatformSharedBuffer::Create(kMaxSizeT);
// But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should
// always fail.
if (buffer)
@ -142,8 +138,7 @@ TEST(SimplePlatformSharedBufferTest, TooBig) {
// and reuse the same address, in which case we'd have to be more careful about
// using the address as the key for unmapping.
TEST(SimplePlatformSharedBufferTest, MappingsDistinct) {
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(100));
auto buffer = SimplePlatformSharedBuffer::Create(100);
std::unique_ptr<PlatformSharedBufferMapping> mapping1(buffer->Map(0, 100));
std::unique_ptr<PlatformSharedBufferMapping> mapping2(buffer->Map(0, 100));
EXPECT_NE(mapping1->GetBase(), mapping2->GetBase());
@ -152,8 +147,7 @@ TEST(SimplePlatformSharedBufferTest, MappingsDistinct) {
TEST(SimplePlatformSharedBufferTest, BufferZeroInitialized) {
static const size_t kSizes[] = {10, 100, 1000, 10000, 100000};
for (size_t i = 0; i < MOJO_ARRAYSIZE(kSizes); i++) {
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(kSizes[i]));
auto buffer = SimplePlatformSharedBuffer::Create(kSizes[i]);
std::unique_ptr<PlatformSharedBufferMapping> mapping(
buffer->Map(0, kSizes[i]));
for (size_t j = 0; j < kSizes[i]; j++) {
@ -170,8 +164,7 @@ TEST(SimplePlatformSharedBufferTest, MappingsOutliveBuffer) {
std::unique_ptr<PlatformSharedBufferMapping> mapping2;
{
scoped_refptr<SimplePlatformSharedBuffer> buffer(
SimplePlatformSharedBuffer::Create(100));
auto buffer = SimplePlatformSharedBuffer::Create(100);
mapping1 = buffer->Map(0, 100);
mapping2 = buffer->Map(50, 50);
static_cast<char*>(mapping1->GetBase())[50] = 'x';

View File

@ -8,6 +8,8 @@
#include "base/time/time.h"
#include "mojo/edk/embedder/simple_platform_shared_buffer.h"
using mojo::util::RefPtr;
namespace mojo {
namespace embedder {
@ -20,12 +22,13 @@ void SimplePlatformSupport::GetCryptoRandomBytes(void* bytes,
base::RandBytes(bytes, num_bytes);
}
PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBuffer(
RefPtr<PlatformSharedBuffer> SimplePlatformSupport::CreateSharedBuffer(
size_t num_bytes) {
return SimplePlatformSharedBuffer::Create(num_bytes);
}
PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBufferFromHandle(
RefPtr<PlatformSharedBuffer>
SimplePlatformSupport::CreateSharedBufferFromHandle(
size_t num_bytes,
ScopedPlatformHandle platform_handle) {
return SimplePlatformSharedBuffer::CreateFromPlatformHandle(

View File

@ -23,8 +23,9 @@ class SimplePlatformSupport final : public PlatformSupport {
MojoTimeTicks GetTimeTicksNow() override;
void GetCryptoRandomBytes(void* bytes, size_t num_bytes) override;
PlatformSharedBuffer* CreateSharedBuffer(size_t num_bytes) override;
PlatformSharedBuffer* CreateSharedBufferFromHandle(
util::RefPtr<PlatformSharedBuffer> CreateSharedBuffer(
size_t num_bytes) override;
util::RefPtr<PlatformSharedBuffer> CreateSharedBufferFromHandle(
size_t num_bytes,
ScopedPlatformHandle platform_handle) override;

View File

@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/logging.h"
#include "mojo/edk/embedder/embedder_internal.h"
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/functions.h"
@ -16,7 +17,7 @@ using mojo::embedder::internal::g_core;
using mojo::system::Core;
using mojo::system::Dispatcher;
using mojo::system::MakeUserPointer;
using mojo::system::RefPtr;
using mojo::util::RefPtr;
// Definitions of the system functions, but with an explicit parameter for the
// core object rather than using the default singleton. Also includes functions

View File

@ -3,6 +3,7 @@
# found in the LICENSE file.
import("../public/mojo_sdk.gni")
import("//testing/test.gni")
# A mojo_edk_source_set is a mojo_sdk_source_set that does not restrict
# external dependencies and understands the following additional variables, all
@ -96,6 +97,78 @@ template("mojo_edk_source_set") {
}
}
template("mojo_edk_unittests") {
test(target_name) {
deps = [
rebase_path("mojo/edk/system/test:run_all_unittests", ".", mojo_root),
]
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.deps)) {
foreach(dep, invoker.deps) {
# The only deps that are not specified relative to the location of the
# Mojo EDK should be on targets within the same file or on a whitelisted
# set of external dependencies.
# TODO(vtl): Get rid of //base dependencies (and stop allowing it).
assert(get_path_info(dep, "dir") == "." || dep == "//testing/gtest" ||
dep == "//base")
deps += [ dep ]
}
}
if (defined(invoker.mojo_sdk_deps)) {
foreach(sdk_dep, invoker.mojo_sdk_deps) {
# Check that the SDK dep was not mistakenly given as an absolute path.
assert(get_path_info(sdk_dep, "abspath") != sdk_dep)
deps += [ rebase_path(sdk_dep, ".", mojo_root) ]
}
}
if (defined(invoker.mojo_edk_deps)) {
foreach(edk_dep, invoker.mojo_edk_deps) {
# Check that the EDK dep was not mistakenly given as an absolute path.
assert(get_path_info(edk_dep, "abspath") != edk_dep)
deps += [ rebase_path(edk_dep, ".", mojo_root) ]
}
}
}
}
template("mojo_edk_perftests") {
test(target_name) {
deps = [
rebase_path("mojo/edk/system/test:run_all_perftests", ".", mojo_root),
]
if (defined(invoker.sources)) {
sources = invoker.sources
}
if (defined(invoker.deps)) {
foreach(dep, invoker.deps) {
# The only deps that are not specified relative to the location of the
# Mojo EDK should be on targets within the same file or on a whitelisted
# set of external dependencies.
# TODO(vtl): Get rid of //base dependencies (and stop allowing it).
assert(get_path_info(dep, "dir") == "." || dep == "//testing/gtest" ||
dep == "//base")
deps += [ dep ]
}
}
if (defined(invoker.mojo_sdk_deps)) {
foreach(sdk_dep, invoker.mojo_sdk_deps) {
# Check that the SDK dep was not mistakenly given as an absolute path.
assert(get_path_info(sdk_dep, "abspath") != sdk_dep)
deps += [ rebase_path(sdk_dep, ".", mojo_root) ]
}
}
if (defined(invoker.mojo_edk_deps)) {
foreach(edk_dep, invoker.mojo_edk_deps) {
# Check that the EDK dep was not mistakenly given as an absolute path.
assert(get_path_info(edk_dep, "abspath") != edk_dep)
deps += [ rebase_path(edk_dep, ".", mojo_root) ]
}
}
}
}
# Build EDK things with static thread annotation analysis enabled.
# TODO(vtl): Should we set this at a higher level?
if (is_clang) {

View File

@ -10,11 +10,8 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
# TODO(vtl): Should we get rid of this?
config("system_config") {
defines = [
# Ensures that dependent projects import the core functions on Windows.
"MOJO_USE_SYSTEM_IMPL",
]
}
component("system") {
@ -83,8 +80,6 @@ component("system") {
"message_pipe_dispatcher.h",
"message_pipe_endpoint.cc",
"message_pipe_endpoint.h",
"mutex.cc",
"mutex.h",
"options_validation.h",
"platform_handle_dispatcher.cc",
"platform_handle_dispatcher.h",
@ -94,10 +89,6 @@ component("system") {
"raw_channel.cc",
"raw_channel.h",
"raw_channel_posix.cc",
"ref_counted.h",
"ref_counted_internal.h",
"ref_ptr.h",
"ref_ptr_internal.h",
"remote_consumer_data_pipe_impl.cc",
"remote_consumer_data_pipe_impl.h",
"remote_data_pipe_ack.h",
@ -109,17 +100,16 @@ component("system") {
"simple_dispatcher.h",
"slave_connection_manager.cc",
"slave_connection_manager.h",
"thread_annotations.h",
"transport_data.cc",
"transport_data.h",
"unique_identifier.cc",
"unique_identifier.h",
"waitable_event.cc",
"waitable_event.h",
"waiter.cc",
"waiter.h",
]
defines = [ "MOJO_SYSTEM_IMPLEMENTATION" ]
all_dependent_configs = [ ":system_config" ]
public_deps = [
@ -147,29 +137,9 @@ group("tests") {
]
}
mojo_edk_source_set("test_utils") {
testonly = true
sources = [
"test_utils.cc",
"test_utils.h",
]
mojo_sdk_public_deps = [
"mojo/public/c/system",
"mojo/public/cpp/system",
]
deps = [
"//base",
"//base/test:test_support",
]
mojo_edk_deps = [ "mojo/edk/embedder:platform" ]
}
test("mojo_system_unittests") {
mojo_edk_unittests("mojo_system_unittests") {
sources = [
# TODO(vtl): This should be in its own mojo_edk_unittests target.
"../test/multiprocess_test_helper_unittest.cc",
"awakable_list_unittest.cc",
"channel_endpoint_id_unittest.cc",
@ -196,21 +166,17 @@ test("mojo_system_unittests") {
"message_pipe_test_utils.h",
"message_pipe_unittest.cc",
"multiprocess_message_pipe_unittest.cc",
"mutex_unittest.cc",
"options_validation_unittest.cc",
"platform_handle_dispatcher_unittest.cc",
"raw_channel_unittest.cc",
"ref_counted_unittest.cc",
"remote_data_pipe_impl_unittest.cc",
"remote_message_pipe_unittest.cc",
"run_all_unittests.cc",
"shared_buffer_dispatcher_unittest.cc",
"simple_dispatcher_unittest.cc",
"test_channel_endpoint_client.cc",
"test_channel_endpoint_client.h",
"test_utils_unittest.cc",
"thread_annotations_unittest.cc",
"unique_identifier_unittest.cc",
"waitable_event_unittest.cc",
"waiter_test_utils.cc",
"waiter_test_utils.h",
"waiter_unittest.cc",
@ -218,33 +184,41 @@ test("mojo_system_unittests") {
deps = [
":system",
":test_utils",
"../embedder:embedder_unittests",
"../test:test_support",
"../util",
"//base",
"//base/test:test_support",
"//testing/gtest",
]
allow_circular_includes_from = [ "../embedder:embedder_unittests" ]
mojo_edk_deps = [
# TODO(vtl): Add separate mojo_edk_unittests targets for these.
"mojo/edk/embedder:unittests",
"mojo/edk/system/test:unittests",
"mojo/edk/util:unittests",
"mojo/edk/system/test",
"mojo/edk/test:test_support",
"mojo/edk/util",
]
}
test("mojo_system_perftests") {
mojo_edk_perftests("mojo_system_perftests") {
sources = [
"message_pipe_perftest.cc",
"message_pipe_test_utils.cc",
"message_pipe_test_utils.h",
"ref_counted_perftest.cc",
]
deps = [
":system",
":test_utils",
"../test:test_support",
"//base",
"//base/test:test_support",
"//base/test:test_support_perf",
"//testing/gtest",
]
mojo_edk_deps = [
# TODO(vtl): Add separate test targets for this.
"mojo/edk/util:perftests",
"mojo/edk/system/test",
"mojo/edk/system/test:perf",
"mojo/edk/test:test_support",
]
}

View File

@ -3,14 +3,15 @@
// found in the LICENSE file.
// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to
// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
// increase tolerance and reduce observed flakiness (though doing so reduces the
// meaningfulness of the test).
#include "mojo/edk/system/awakable_list.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/sleep.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/system/waiter_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -53,7 +54,7 @@ TEST(AwakableListTest, BasicCancel) {
test::SimpleWaiterThread thread(&result, &context);
awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.CancelAll();
} // Join |thread|.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
@ -100,7 +101,7 @@ TEST(AwakableListTest, BasicAwakeSatisfied) {
test::SimpleWaiterThread thread(&result, &context);
awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.AwakeForStateChange(HandleSignalsState(
MOJO_HANDLE_SIGNAL_READABLE,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
@ -146,7 +147,7 @@ TEST(AwakableListTest, BasicAwakeUnsatisfiable) {
test::SimpleWaiterThread thread(&result, &context);
awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.AwakeForStateChange(HandleSignalsState(
MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
awakable_list.Remove(thread.waiter());
@ -176,7 +177,7 @@ TEST(AwakableListTest, MultipleAwakables) {
test::SimpleWaiterThread thread2(&result2, &context2);
awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
thread2.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.CancelAll();
} // Join threads.
EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
@ -193,7 +194,7 @@ TEST(AwakableListTest, MultipleAwakables) {
test::SimpleWaiterThread thread2(&result2, &context2);
awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4);
thread2.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.AwakeForStateChange(HandleSignalsState(
MOJO_HANDLE_SIGNAL_READABLE,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
@ -214,7 +215,7 @@ TEST(AwakableListTest, MultipleAwakables) {
test::SimpleWaiterThread thread2(&result2, &context2);
awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6);
thread2.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
awakable_list.AwakeForStateChange(HandleSignalsState(
MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE));
awakable_list.Remove(thread2.waiter());
@ -232,7 +233,7 @@ TEST(AwakableListTest, MultipleAwakables) {
awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7);
thread1.Start();
test::Sleep(1 * test::EpsilonDeadline());
test::Sleep(1 * test::EpsilonTimeout());
// Should do nothing.
awakable_list.AwakeForStateChange(HandleSignalsState(
@ -243,7 +244,7 @@ TEST(AwakableListTest, MultipleAwakables) {
awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8);
thread2.Start();
test::Sleep(1 * test::EpsilonDeadline());
test::Sleep(1 * test::EpsilonTimeout());
// Awake #1.
awakable_list.AwakeForStateChange(HandleSignalsState(
@ -251,7 +252,7 @@ TEST(AwakableListTest, MultipleAwakables) {
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
awakable_list.Remove(thread1.waiter());
test::Sleep(1 * test::EpsilonDeadline());
test::Sleep(1 * test::EpsilonTimeout());
test::SimpleWaiterThread thread3(&result3, &context3);
awakable_list.Add(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9);
@ -261,7 +262,7 @@ TEST(AwakableListTest, MultipleAwakables) {
awakable_list.Add(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10);
thread4.Start();
test::Sleep(1 * test::EpsilonDeadline());
test::Sleep(1 * test::EpsilonTimeout());
// Awake #2 and #3 for unsatisfiability.
awakable_list.AwakeForStateChange(HandleSignalsState(

View File

@ -14,6 +14,10 @@
#include "mojo/edk/system/endpoint_relayer.h"
#include "mojo/edk/system/transport_data.h"
using mojo::util::MakeRefCounted;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -16,10 +16,11 @@
#include "mojo/edk/system/channel_endpoint_id.h"
#include "mojo/edk/system/incoming_endpoint.h"
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/ref_counted.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_counted.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
@ -50,10 +51,10 @@ class MessageInTransitQueue;
// |ChannelEndpointClient| (e.g., |MessagePipe|), |ChannelEndpoint|, |Channel|.
// Thus |Channel| may not call into |ChannelEndpoint| with |Channel|'s lock
// held.
class Channel final : public RefCountedThreadSafe<Channel>,
class Channel final : public util::RefCountedThreadSafe<Channel>,
public RawChannel::Delegate {
public:
// Note: Use |MakeRefCounted<Channel>()|.
// Note: Use |util::MakeRefCounted<Channel>()|.
// This must be called on the creation thread before any other methods are
// called, and before references to this object are given to any other
@ -85,7 +86,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
//
// (Bootstrapping is symmetric: Both sides call this, which will establish the
// first connection across a channel.)
void SetBootstrapEndpoint(RefPtr<ChannelEndpoint>&& endpoint);
void SetBootstrapEndpoint(util::RefPtr<ChannelEndpoint>&& endpoint);
// Like |SetBootstrapEndpoint()|, but with explicitly-specified local and
// remote IDs.
@ -93,7 +94,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
// (Bootstrapping is still symmetric, though the sides should obviously
// interchange local and remote IDs. This can be used to allow multiple
// "bootstrap" endpoints, though this is really most useful for testing.)
void SetBootstrapEndpointWithIds(RefPtr<ChannelEndpoint>&& endpoint,
void SetBootstrapEndpointWithIds(util::RefPtr<ChannelEndpoint>&& endpoint,
ChannelEndpointId local_id,
ChannelEndpointId remote_id);
@ -149,14 +150,15 @@ class Channel final : public RefCountedThreadSafe<Channel>,
MessageInTransitQueue* message_queue);
// This one returns the |ChannelEndpoint| for the serialized endpoint (which
// can be used by, e.g., a |ProxyMessagePipeEndpoint|.
RefPtr<ChannelEndpoint> SerializeEndpointWithLocalPeer(
util::RefPtr<ChannelEndpoint> SerializeEndpointWithLocalPeer(
void* destination,
MessageInTransitQueue* message_queue,
RefPtr<ChannelEndpointClient>&& endpoint_client,
util::RefPtr<ChannelEndpointClient>&& endpoint_client,
unsigned endpoint_client_port);
void SerializeEndpointWithRemotePeer(void* destination,
MessageInTransitQueue* message_queue,
RefPtr<ChannelEndpoint>&& peer_endpoint);
void SerializeEndpointWithRemotePeer(
void* destination,
MessageInTransitQueue* message_queue,
util::RefPtr<ChannelEndpoint>&& peer_endpoint);
// Deserializes an endpoint that was sent from the peer |Channel| (using
// |SerializeEndpoint...()|. |source| should be (a copy of) the data that
@ -164,7 +166,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
// |GetSerializedEndpointSize()| bytes. This returns the deserialized
// |IncomingEndpoint| (which can be converted into a |MessagePipe|) or null on
// error.
RefPtr<IncomingEndpoint> DeserializeEndpoint(const void* source);
util::RefPtr<IncomingEndpoint> DeserializeEndpoint(const void* source);
// See |RawChannel::GetSerializedPlatformHandleSize()|.
size_t GetSerializedPlatformHandleSize() const;
@ -224,7 +226,8 @@ class Channel final : public RefCountedThreadSafe<Channel>,
// for which |is_remote()| returns true).
//
// TODO(vtl): Maybe limit the number of attached message pipes.
ChannelEndpointId AttachAndRunEndpoint(RefPtr<ChannelEndpoint>&& endpoint);
ChannelEndpointId AttachAndRunEndpoint(
util::RefPtr<ChannelEndpoint>&& endpoint);
// Helper to send channel control messages. Returns true on success. Callable
// from any thread.
@ -246,7 +249,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
// TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|,
// once clang actually checks such annotations.
// https://github.com/domokit/mojo/issues/313
mutable Mutex mutex_;
mutable util::Mutex mutex_;
std::unique_ptr<RawChannel> raw_channel_ MOJO_GUARDED_BY(mutex_);
bool is_running_ MOJO_GUARDED_BY(mutex_);
@ -257,7 +260,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
ChannelManager* channel_manager_ MOJO_GUARDED_BY(mutex_);
using IdToEndpointMap =
std::unordered_map<ChannelEndpointId, RefPtr<ChannelEndpoint>>;
std::unordered_map<ChannelEndpointId, util::RefPtr<ChannelEndpoint>>;
// Map from local IDs to endpoints. If the endpoint is null, this means that
// we're just waiting for the remove ack before removing the entry.
IdToEndpointMap local_id_to_endpoint_map_ MOJO_GUARDED_BY(mutex_);
@ -265,7 +268,7 @@ class Channel final : public RefCountedThreadSafe<Channel>,
LocalChannelEndpointIdGenerator local_id_generator_ MOJO_GUARDED_BY(mutex_);
using IdToIncomingEndpointMap =
std::unordered_map<ChannelEndpointId, RefPtr<IncomingEndpoint>>;
std::unordered_map<ChannelEndpointId, util::RefPtr<IncomingEndpoint>>;
// Map from local IDs to incoming endpoints (i.e., those received inside other
// messages, but not yet claimed via |DeserializeEndpoint()|).
IdToIncomingEndpointMap incoming_endpoints_ MOJO_GUARDED_BY(mutex_);

View File

@ -12,6 +12,9 @@
#include "mojo/edk/system/channel_endpoint_client.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -9,9 +9,10 @@
#include "mojo/edk/system/channel_endpoint_id.h"
#include "mojo/edk/system/message_in_transit_queue.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_counted.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_counted.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -109,9 +110,10 @@ class MessageInTransit;
// simultaneously, and both sides send "remove" messages). In that
// case, it must still remain alive until it receives the "remove
// ack" (and it must ack the "remove" message that it received).
class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
class ChannelEndpoint final
: public util::RefCountedThreadSafe<ChannelEndpoint> {
public:
// Note: Use |MakeRefCounted<ChannelEndpoint>()|.
// Note: Use |util::MakeRefCounted<ChannelEndpoint>()|.
// Methods called by |ChannelEndpointClient|:
@ -127,7 +129,7 @@ class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
// This returns true in the typical case, and false if this endpoint has been
// detached from the channel, in which case the caller should probably call
// its (new) client's |OnDetachFromChannel()|.
bool ReplaceClient(RefPtr<ChannelEndpointClient>&& client,
bool ReplaceClient(util::RefPtr<ChannelEndpointClient>&& client,
unsigned client_port);
// Called before the |ChannelEndpointClient| gives up its reference to this
@ -161,7 +163,7 @@ class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
// in which case |message_queue| should not be null. In that case, this
// endpoint will simply send queued messages upon being attached to a
// |Channel| and immediately detach itself.
ChannelEndpoint(RefPtr<ChannelEndpointClient>&& client,
ChannelEndpoint(util::RefPtr<ChannelEndpointClient>&& client,
unsigned client_port,
MessageInTransitQueue* message_queue = nullptr);
@ -177,7 +179,7 @@ class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
// this does not call |channel_->DetachEndpoint()|.
void DieNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
Mutex mutex_;
util::Mutex mutex_;
enum class State {
// |AttachAndRun()| has not been called yet (|channel_| is null).
@ -192,9 +194,9 @@ class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
// |client_| must be valid whenever it is non-null. Before |*client_| gives up
// its reference to this object, it must call |DetachFromClient()|.
// NOTE: This is a |RefPtr<>|, rather than a raw pointer, since the |Channel|
// needs to keep the client (e.g., |MessagePipe|) alive for the "proxy-proxy"
// case.
// NOTE: This is a |util:RefPtr<>|, rather than a raw pointer, since the
// |Channel| needs to keep the client (e.g., |MessagePipe|) alive for the
// "proxy-proxy" case.
// WARNING: |ChannelEndpointClient| methods must not be called under |mutex_|.
// Thus to make such a call, a reference must first be taken under |mutex_|
// and the lock released.
@ -204,7 +206,7 @@ class ChannelEndpoint final : public RefCountedThreadSafe<ChannelEndpoint> {
// WARNING: Beware of interactions with |ReplaceClient()|. By the time the
// call is made, the client may have changed. This must be detected and dealt
// with.
RefPtr<ChannelEndpointClient> client_ MOJO_GUARDED_BY(mutex_);
util::RefPtr<ChannelEndpointClient> client_ MOJO_GUARDED_BY(mutex_);
unsigned client_port_ MOJO_GUARDED_BY(mutex_);
// |channel_| must be valid whenever it is non-null. Before |*channel_| gives

View File

@ -5,7 +5,7 @@
#ifndef MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_
#define MOJO_EDK_SYSTEM_CHANNEL_ENDPOINT_CLIENT_H_
#include "mojo/edk/system/ref_counted.h"
#include "mojo/edk/util/ref_counted.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -30,7 +30,7 @@ class MessageInTransit;
// |ChannelEndpoint| has apparently relinquished its pointer to the
// |ChannelEndpointClient|).
class ChannelEndpointClient
: public RefCountedThreadSafe<ChannelEndpointClient> {
: public util::RefCountedThreadSafe<ChannelEndpointClient> {
public:
// Called by |ChannelEndpoint| in response to its |OnReadMessage()|, which is
// called by |Channel| when it receives a message for the |ChannelEndpoint|.

View File

@ -7,15 +7,17 @@
#include <memory>
#include <utility>
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "mojo/edk/system/channel_test_base.h"
#include "mojo/edk/system/message_in_transit_queue.h"
#include "mojo/edk/system/message_in_transit_test_utils.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/test_channel_endpoint_client.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MakeRefCounted;
namespace mojo {
namespace system {
namespace {
@ -59,7 +61,7 @@ TEST_F(ChannelEndpointTest, Basic) {
channel(1)->SetBootstrapEndpoint(endpoint1.Clone());
// We'll receive a message on channel/client 0.
base::WaitableEvent read_event(true, false);
ManualResetWaitableEvent read_event;
client0->SetReadEvent(&read_event);
// Make a test message.
@ -69,14 +71,14 @@ TEST_F(ChannelEndpointTest, Basic) {
// Check that our test utility works (at least in one direction).
test::VerifyTestMessage(send_message.get(), message_id);
// Event shouldn't be signalled yet.
EXPECT_FALSE(read_event.IsSignaled());
// Event shouldn't be signaled yet.
EXPECT_FALSE(read_event.IsSignaledForTest());
// Send it through channel/endpoint 1.
EXPECT_TRUE(endpoint1->EnqueueMessage(std::move(send_message)));
// Wait to receive it.
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
client0->SetReadEvent(nullptr);
// Check the received message.
@ -113,10 +115,10 @@ TEST_F(ChannelEndpointTest, Prequeued) {
EXPECT_TRUE(endpoint1->EnqueueMessage(test::MakeTestMessage(6)));
// Wait for the messages.
base::WaitableEvent read_event(true, false);
ManualResetWaitableEvent read_event;
client0->SetReadEvent(&read_event);
for (size_t i = 0; client0->NumMessages() < 6 && i < 6; i++) {
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
read_event.Reset();
}
client0->SetReadEvent(nullptr);

View File

@ -12,6 +12,10 @@
#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
using mojo::util::MakeRefCounted;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -10,12 +10,12 @@
#include <unordered_map>
#include "base/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "mojo/edk/embedder/platform_task_runner.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel_id.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace base {
@ -71,7 +71,7 @@ class ChannelManager {
// constructor). |channel_id| should be a valid |ChannelId| (i.e., nonzero)
// not "assigned" to any other |Channel| being managed by this
// |ChannelManager|.
RefPtr<MessagePipeDispatcher> CreateChannelOnIOThread(
util::RefPtr<MessagePipeDispatcher> CreateChannelOnIOThread(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle);
@ -79,7 +79,7 @@ class ChannelManager {
// pipe. Returns the newly-created |Channel|.
// TODO(vtl): Maybe get rid of the others (and bootstrap message pipes in
// general).
RefPtr<Channel> CreateChannelWithoutBootstrapOnIOThread(
util::RefPtr<Channel> CreateChannelWithoutBootstrapOnIOThread(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle);
@ -87,14 +87,14 @@ class ChannelManager {
// completion, will call |callback| (using |callback_thread_task_runner| if it
// is non-null, else on the I/O thread). Note: This will always post a task to
// the I/O thread, even if called from that thread.
RefPtr<MessagePipeDispatcher> CreateChannel(
util::RefPtr<MessagePipeDispatcher> CreateChannel(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
const base::Closure& callback,
embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner);
// Gets the |Channel| with the given ID (which must exist).
RefPtr<Channel> GetChannel(ChannelId channel_id) const;
util::RefPtr<Channel> GetChannel(ChannelId channel_id) const;
// Informs the channel manager (and thus channel) that it will be shutdown
// soon (by calling |ShutdownChannel()|). Calling this is optional (and may in
@ -129,10 +129,10 @@ class ChannelManager {
// Used by |CreateChannelOnIOThread()| and |CreateChannelHelper()|. Called on
// the I/O thread. |bootstrap_channel_endpoint| is optional and may be null.
// Returns the newly-created |Channel|.
RefPtr<Channel> CreateChannelOnIOThreadHelper(
util::RefPtr<Channel> CreateChannelOnIOThreadHelper(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
RefPtr<ChannelEndpoint>&& bootstrap_channel_endpoint);
util::RefPtr<ChannelEndpoint>&& bootstrap_channel_endpoint);
// Used by |CreateChannel()|. Called on the I/O thread.
// TODO(vtl): |bootstrap_channel_endpoint| should be an rvalue reference, but
@ -140,7 +140,7 @@ class ChannelManager {
void CreateChannelHelper(
ChannelId channel_id,
embedder::ScopedPlatformHandle platform_handle,
RefPtr<ChannelEndpoint> bootstrap_channel_endpoint,
util::RefPtr<ChannelEndpoint> bootstrap_channel_endpoint,
const base::Closure& callback,
embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner);
@ -153,9 +153,10 @@ class ChannelManager {
// TODO(vtl): Annotate the above rule using |MOJO_ACQUIRED_{BEFORE,AFTER}()|,
// once clang actually checks such annotations.
// https://github.com/domokit/mojo/issues/313
mutable Mutex mutex_;
mutable util::Mutex mutex_;
using ChannelIdToChannelMap = std::unordered_map<ChannelId, RefPtr<Channel>>;
using ChannelIdToChannelMap =
std::unordered_map<ChannelId, util::RefPtr<Channel>>;
ChannelIdToChannelMap channels_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelManager);

View File

@ -14,10 +14,12 @@
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/test/simple_test_thread.h"
#include "mojo/edk/system/test/simple_test_thread.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -53,12 +55,16 @@ TEST_F(ChannelManagerTest, Basic) {
RefPtr<Channel> ch = channel_manager().GetChannel(id);
EXPECT_TRUE(ch);
// |ChannelManager| should have a ref.
EXPECT_FALSE(ch->HasOneRef());
channel_manager().WillShutdownChannel(id);
// |ChannelManager| should still have a ref.
EXPECT_FALSE(ch->HasOneRef());
channel_manager().ShutdownChannelOnIOThread(id);
// |ChannelManager| should have given up its ref.
ch->AssertHasOneRef();
EXPECT_TRUE(ch->HasOneRef());
EXPECT_EQ(MOJO_RESULT_OK, d->Close());
}
@ -83,18 +89,19 @@ TEST_F(ChannelManagerTest, TwoChannels) {
// Calling |WillShutdownChannel()| multiple times (on |id1|) is okay.
channel_manager().WillShutdownChannel(id1);
channel_manager().WillShutdownChannel(id1);
EXPECT_FALSE(ch1->HasOneRef());
// Not calling |WillShutdownChannel()| (on |id2|) is okay too.
channel_manager().ShutdownChannelOnIOThread(id1);
ch1->AssertHasOneRef();
EXPECT_TRUE(ch1->HasOneRef());
channel_manager().ShutdownChannelOnIOThread(id2);
ch2->AssertHasOneRef();
EXPECT_TRUE(ch2->HasOneRef());
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
EXPECT_EQ(MOJO_RESULT_OK, d2->Close());
}
class OtherThread : public mojo::test::SimpleTestThread {
class OtherThread : public test::SimpleTestThread {
public:
// Note: There should be no other refs to the channel identified by
// |channel_id| outside the channel manager.
@ -115,8 +122,12 @@ class OtherThread : public mojo::test::SimpleTestThread {
// You can use any unique, nonzero value as the ID.
RefPtr<Channel> ch = channel_manager_->GetChannel(channel_id_);
// |ChannelManager| should have a ref.
EXPECT_FALSE(ch->HasOneRef());
channel_manager_->WillShutdownChannel(channel_id_);
// |ChannelManager| should still have a ref.
EXPECT_FALSE(ch->HasOneRef());
{
base::MessageLoop message_loop;

View File

@ -11,12 +11,14 @@
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/system/raw_channel.h"
using mojo::util::MakeRefCounted;
namespace mojo {
namespace system {
namespace test {
ChannelTestBase::ChannelTestBase()
: io_thread_(mojo::test::TestIOThread::StartMode::AUTO) {}
: io_thread_(TestIOThread::StartMode::AUTO) {}
ChannelTestBase::~ChannelTestBase() {
}

View File

@ -10,8 +10,8 @@
#include "base/bind.h"
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/test/test_io_thread.h"
#include "mojo/edk/system/test/test_io_thread.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -43,17 +43,17 @@ class ChannelTestBase : public testing::Test {
void ShutdownChannelOnIOThread(unsigned i);
void ShutdownAndReleaseChannelOnIOThread(unsigned i);
mojo::test::TestIOThread* io_thread() { return &io_thread_; }
TestIOThread* io_thread() { return &io_thread_; }
Channel* channel(unsigned i) { return channels_[i].get(); }
RefPtr<Channel>* mutable_channel(unsigned i) { return &channels_[i]; }
util::RefPtr<Channel>* mutable_channel(unsigned i) { return &channels_[i]; }
private:
void SetUpOnIOThread();
embedder::SimplePlatformSupport platform_support_;
mojo::test::TestIOThread io_thread_;
TestIOThread io_thread_;
std::unique_ptr<RawChannel> raw_channels_[2];
RefPtr<Channel> channels_[2];
util::RefPtr<Channel> channels_[2];
MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelTestBase);
};

View File

@ -10,9 +10,10 @@
#include "mojo/edk/system/channel_endpoint_id.h"
#include "mojo/edk/system/channel_test_base.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/util/ref_ptr.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
@ -29,7 +30,7 @@ TEST_F(ChannelTest, InitShutdown) {
PostMethodToIOThreadAndWait(&ChannelTest::ShutdownChannelOnIOThread, 0);
// Okay to destroy |Channel| on not-the-I/O-thread.
channel(0)->AssertHasOneRef();
EXPECT_TRUE(channel(0)->HasOneRef());
*mutable_channel(0) = nullptr;
}
@ -47,7 +48,7 @@ TEST_F(ChannelTest, CloseBeforeRun) {
PostMethodToIOThreadAndWait(&ChannelTest::ShutdownChannelOnIOThread, 0);
channel(0)->AssertHasOneRef();
EXPECT_TRUE(channel(0)->HasOneRef());
}
// ChannelTest.ShutdownAfterAttachAndRun ---------------------------------------
@ -79,7 +80,7 @@ TEST_F(ChannelTest, ShutdownAfterAttach) {
mp->Close(0);
channel(0)->AssertHasOneRef();
EXPECT_TRUE(channel(0)->HasOneRef());
}
// ChannelTest.WaitAfterAttachRunAndShutdown -----------------------------------
@ -105,7 +106,7 @@ TEST_F(ChannelTest, WaitAfterAttachRunAndShutdown) {
mp->Close(0);
channel(0)->AssertHasOneRef();
EXPECT_TRUE(channel(0)->HasOneRef());
}
// ChannelTest.EndpointChannelShutdownRace -------------------------------------

View File

@ -9,7 +9,7 @@
#include "mojo/edk/system/connection_identifier.h"
#include "mojo/edk/system/process_identifier.h"
#include "mojo/edk/system/thread_annotations.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {

View File

@ -26,6 +26,9 @@
#include "mojo/public/c/system/macros.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -11,8 +11,9 @@
#include "mojo/edk/system/handle_table.h"
#include "mojo/edk/system/mapping_table.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/message_pipe.h"
@ -48,7 +49,7 @@ class Core {
// Looks up the dispatcher for the given handle. Returns null if the handle is
// invalid.
RefPtr<Dispatcher> GetDispatcher(MojoHandle handle);
util::RefPtr<Dispatcher> GetDispatcher(MojoHandle handle);
// Like |GetDispatcher()|, but also removes the handle from the handle table.
// On success, gets the dispatcher for a given handle (which should not be
@ -57,7 +58,7 @@ class Core {
// |MOJO_RESULT_INVALID_ARGUMENT| if there's no dispatcher for the given
// handle or |MOJO_RESULT_BUSY| if the handle is marked as busy.)
MojoResult GetAndRemoveDispatcher(MojoHandle handle,
RefPtr<Dispatcher>* dispatcher);
util::RefPtr<Dispatcher>* dispatcher);
// Watches on the given handle for the given signals, calling |callback| when
// a signal is satisfied or when all signals become unsatisfiable. |callback|
@ -175,10 +176,10 @@ class Core {
// TODO(vtl): |handle_table_mutex_| should be a reader-writer lock (if only we
// had them).
Mutex handle_table_mutex_;
util::Mutex handle_table_mutex_;
HandleTable handle_table_ MOJO_GUARDED_BY(handle_table_mutex_);
Mutex mapping_table_mutex_;
util::Mutex mapping_table_mutex_;
MappingTable mapping_table_ MOJO_GUARDED_BY(mapping_table_mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(Core);

View File

@ -11,9 +11,12 @@
#include "mojo/edk/system/core.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace test {

View File

@ -6,7 +6,8 @@
#define MOJO_EDK_SYSTEM_CORE_TEST_BASE_H_
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@ -88,7 +89,7 @@ class CoreTestBase_MockHandleInfo {
void AwakableWasAdded(Awakable*);
private:
mutable Mutex mutex_;
mutable util::Mutex mutex_;
unsigned ctor_call_count_ MOJO_GUARDED_BY(mutex_);
unsigned dtor_call_count_ MOJO_GUARDED_BY(mutex_);
unsigned close_call_count_ MOJO_GUARDED_BY(mutex_);

View File

@ -11,7 +11,7 @@
#include "base/bind.h"
#include "mojo/edk/system/awakable.h"
#include "mojo/edk/system/core_test_base.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/sleep.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -30,7 +30,7 @@ TEST_F(CoreTest, GetTimeTicksNow) {
const MojoTimeTicks start = core()->GetTimeTicksNow();
EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
<< "GetTimeTicksNow should return nonzero value";
test::Sleep(test::DeadlineFromMilliseconds(15));
test::SleepMilliseconds(15u);
const MojoTimeTicks finish = core()->GetTimeTicksNow();
// Allow for some fuzz in sleep.
EXPECT_GE((finish - start), static_cast<MojoTimeTicks>(8000))

View File

@ -25,6 +25,9 @@
#include "mojo/edk/system/remote_producer_data_pipe_impl.h"
#include "mojo/edk/util/make_unique.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -14,9 +14,9 @@
#include "mojo/edk/system/channel_endpoint_client.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/thread_annotations.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
@ -58,7 +58,7 @@ class DataPipe final : public ChannelEndpointClient {
// |ValidateOptions()|. In particular: |struct_size| is ignored (so
// |validated_options| must be the current version of the struct) and
// |capacity_num_bytes| must be nonzero.
static RefPtr<DataPipe> CreateLocal(
static util::RefPtr<DataPipe> CreateLocal(
const MojoCreateDataPipeOptions& validated_options);
// Creates a data pipe with a remote producer and a local consumer, using an
@ -67,10 +67,10 @@ class DataPipe final : public ChannelEndpointClient {
// |channel_endpoint| is null, this will create a "half-open" data pipe (with
// only the consumer open). Note that this may fail, in which case it returns
// null.
static RefPtr<DataPipe> CreateRemoteProducerFromExisting(
static util::RefPtr<DataPipe> CreateRemoteProducerFromExisting(
const MojoCreateDataPipeOptions& validated_options,
MessageInTransitQueue* message_queue,
RefPtr<ChannelEndpoint>&& channel_endpoint);
util::RefPtr<ChannelEndpoint>&& channel_endpoint);
// Creates a data pipe with a local producer and a remote consumer, using an
// existing |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and taking
@ -78,11 +78,11 @@ class DataPipe final : public ChannelEndpointClient {
// (|message_queue| may be null). If |channel_endpoint| is null, this will
// create a "half-open" data pipe (with only the producer open). Note that
// this may fail, in which case it returns null.
static RefPtr<DataPipe> CreateRemoteConsumerFromExisting(
static util::RefPtr<DataPipe> CreateRemoteConsumerFromExisting(
const MojoCreateDataPipeOptions& validated_options,
size_t consumer_num_bytes,
MessageInTransitQueue* message_queue,
RefPtr<ChannelEndpoint>&& channel_endpoint);
util::RefPtr<ChannelEndpoint>&& channel_endpoint);
// Used by |DataPipeProducerDispatcher::Deserialize()|. Returns true on
// success (in which case, |*data_pipe| is set appropriately) and false on
@ -90,7 +90,7 @@ class DataPipe final : public ChannelEndpointClient {
static bool ProducerDeserialize(Channel* channel,
const void* source,
size_t size,
RefPtr<DataPipe>* data_pipe);
util::RefPtr<DataPipe>* data_pipe);
// Used by |DataPipeConsumerDispatcher::Deserialize()|. Returns true on
// success (in which case, |*data_pipe| is set appropriately) and false on
@ -98,7 +98,7 @@ class DataPipe final : public ChannelEndpointClient {
static bool ConsumerDeserialize(Channel* channel,
const void* source,
size_t size,
RefPtr<DataPipe>* data_pipe);
util::RefPtr<DataPipe>* data_pipe);
// These are called by the producer dispatcher to implement its methods of
// corresponding names.
@ -265,7 +265,7 @@ class DataPipe final : public ChannelEndpointClient {
MSVC_SUPPRESS_WARNING(4324)
const MojoCreateDataPipeOptions validated_options_;
mutable Mutex mutex_;
mutable util::Mutex mutex_;
// *Known* state of producer or consumer.
bool producer_open_ MOJO_GUARDED_BY(mutex_);
bool consumer_open_ MOJO_GUARDED_BY(mutex_);

View File

@ -10,6 +10,9 @@
#include "mojo/edk/system/data_pipe.h"
#include "mojo/edk/system/memory.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -6,7 +6,8 @@
#define MOJO_EDK_SYSTEM_DATA_PIPE_CONSUMER_DISPATCHER_H_
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -19,21 +20,20 @@ class DataPipe;
// thread-safe.
class DataPipeConsumerDispatcher final : public Dispatcher {
public:
static RefPtr<DataPipeConsumerDispatcher> Create() {
static util::RefPtr<DataPipeConsumerDispatcher> Create() {
return AdoptRef(new DataPipeConsumerDispatcher());
}
// Must be called before any other methods.
void Init(RefPtr<DataPipe>&& data_pipe) MOJO_NOT_THREAD_SAFE;
void Init(util::RefPtr<DataPipe>&& data_pipe) MOJO_NOT_THREAD_SAFE;
// |Dispatcher| public methods:
Type GetType() const override;
// The "opposite" of |SerializeAndClose()|. (Typically this is called by
// |Dispatcher::Deserialize()|.)
static RefPtr<DataPipeConsumerDispatcher> Deserialize(Channel* channel,
const void* source,
size_t size);
static util::RefPtr<DataPipeConsumerDispatcher>
Deserialize(Channel* channel, const void* source, size_t size);
// Get access to the |DataPipe| for testing.
DataPipe* GetDataPipeForTest();
@ -45,7 +45,8 @@ class DataPipeConsumerDispatcher final : public Dispatcher {
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override;
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
override;
MojoResult ReadDataImplNoLock(UserPointer<void> elements,
UserPointer<uint32_t> num_bytes,
MojoReadDataFlags flags) override;
@ -73,7 +74,7 @@ class DataPipeConsumerDispatcher final : public Dispatcher {
bool IsBusyNoLock() const override;
// This will be null if closed.
RefPtr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex());
util::RefPtr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex());
MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeConsumerDispatcher);
};

View File

@ -13,7 +13,7 @@
#include "mojo/edk/system/data_pipe.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/thread_annotations.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/macros.h"
#include "mojo/public/c/system/types.h"

View File

@ -25,13 +25,17 @@
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/sleep.h"
#include "mojo/edk/system/test/test_io_thread.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/test/test_io_thread.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::MakeRefCounted;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -223,7 +227,7 @@ class LocalDataPipeImplTestHelper : public DataPipeImplTestHelper {
class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper {
public:
RemoteDataPipeImplTestHelper()
: io_thread_(mojo::test::TestIOThread::StartMode::AUTO) {}
: io_thread_(test::TestIOThread::StartMode::AUTO) {}
~RemoteDataPipeImplTestHelper() override {}
void SetUp() override {
@ -279,7 +283,7 @@ class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper {
transport.End();
}
uint32_t context = 0;
ASSERT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context));
ASSERT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionTimeout(), &context));
EXPECT_EQ(987u, context);
HandleSignalsState hss = HandleSignalsState();
message_pipe(dest_i)->RemoveAwakable(0, &waiter, &hss);
@ -299,7 +303,7 @@ class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper {
ASSERT_EQ(1u, read_dispatchers.size());
ASSERT_EQ(1u, read_num_dispatchers);
ASSERT_TRUE(read_dispatchers[0]);
read_dispatchers[0]->AssertHasOneRef();
EXPECT_TRUE(read_dispatchers[0]->HasOneRef());
*to_receive = read_dispatchers[0];
}
@ -344,7 +348,7 @@ class RemoteDataPipeImplTestHelper : public DataPipeImplTestHelper {
}
embedder::SimplePlatformSupport platform_support_;
mojo::test::TestIOThread io_thread_;
test::TestIOThread io_thread_;
RefPtr<Channel> channels_[2];
RefPtr<MessagePipe> message_pipes_[2];
@ -372,7 +376,7 @@ class RemoteProducerDataPipeImplTestHelper
SendDispatcher(0, to_send, &to_receive);
// |to_send| should have been closed. This is |DCHECK()|ed when it is
// destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType());
@ -421,7 +425,7 @@ class RemoteConsumerDataPipeImplTestHelper
SendDispatcher(0, to_send, &to_receive);
// |to_send| should have been closed. This is |DCHECK()|ed when it is
// destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType());
@ -475,7 +479,7 @@ class RemoteProducerDataPipeImplTestHelper2
SendDispatcher(0, to_send, &to_receive);
// |to_send| should have been closed. This is |DCHECK()|ed when it is
// destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType());
to_send = RefPtr<DataPipeProducerDispatcher>(
@ -486,7 +490,7 @@ class RemoteProducerDataPipeImplTestHelper2
SendDispatcher(1, to_send, &to_receive);
// |producer_dispatcher_| should have been closed. This is |DCHECK()|ed when
// it is destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_PRODUCER, to_receive->GetType());
@ -522,7 +526,7 @@ class RemoteConsumerDataPipeImplTestHelper2
SendDispatcher(0, to_send, &to_receive);
// |to_send| should have been closed. This is |DCHECK()|ed when it is
// destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType());
to_send = RefPtr<DataPipeConsumerDispatcher>(
@ -533,7 +537,7 @@ class RemoteConsumerDataPipeImplTestHelper2
SendDispatcher(1, to_send, &to_receive);
// |consumer_dispatcher_| should have been closed. This is |DCHECK()|ed when
// it is destroyed.
to_send->AssertHasOneRef();
EXPECT_TRUE(to_send->HasOneRef());
to_send = nullptr;
ASSERT_EQ(Dispatcher::Type::DATA_PIPE_CONSUMER, to_receive->GetType());
@ -652,7 +656,7 @@ TYPED_TEST(DataPipeImplTest, SimpleReadWrite) {
// Wait.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionTimeout(), &context));
EXPECT_EQ(123u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -805,7 +809,7 @@ TYPED_TEST(DataPipeImplTest, BasicProducerWaiting) {
// Wait for data to become available to the consumer.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(1234u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&cwaiter, &hss);
@ -856,7 +860,7 @@ TYPED_TEST(DataPipeImplTest, BasicProducerWaiting) {
// Waiting should now succeed.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(78u, context);
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&pwaiter, &hss);
@ -900,7 +904,7 @@ TYPED_TEST(DataPipeImplTest, BasicProducerWaiting) {
// Waiting should succeed.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, pwaiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(90u, context);
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&pwaiter, &hss);
@ -928,7 +932,7 @@ TYPED_TEST(DataPipeImplTest, BasicProducerWaiting) {
// It should now be never-writable.
context = 0;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
pwaiter.Wait(test::TinyDeadline(), &context));
pwaiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&pwaiter, &hss);
@ -963,7 +967,7 @@ TYPED_TEST(DataPipeImplTest, PeerClosedProducerWaiting) {
// It should be signaled.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&waiter, &hss);
@ -998,7 +1002,7 @@ TYPED_TEST(DataPipeImplTest, PeerClosedConsumerWaiting) {
// It should be signaled.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1048,7 +1052,7 @@ TYPED_TEST(DataPipeImplTest, BasicConsumerWaiting) {
// Wait for readability (needed for remote cases).
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(34u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1120,7 +1124,7 @@ TYPED_TEST(DataPipeImplTest, BasicConsumerWaiting) {
// Waiting should now succeed.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(90u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1152,7 +1156,7 @@ TYPED_TEST(DataPipeImplTest, BasicConsumerWaiting) {
// Wait for the peer closed signal.
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1223,7 +1227,7 @@ TYPED_TEST(DataPipeImplTest, ConsumerWaitingTwoPhase) {
// Wait for readability (needed for remote cases).
context = 0;
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1280,7 +1284,7 @@ TYPED_TEST(DataPipeImplTest, ConsumerWaitingTwoPhase) {
// Should be never-readable.
context = 0;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
waiter.Wait(test::TinyDeadline(), &context));
waiter.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(56u, context);
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
@ -1356,7 +1360,7 @@ TYPED_TEST(DataPipeImplTest, BasicTwoPhaseWaiting) {
hss.satisfiable_signals);
// It should become readable.
EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, cwaiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&cwaiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -1485,7 +1489,7 @@ TYPED_TEST(DataPipeImplTest, AllOrNone) {
// available at once (except that in current implementations, with reasonable
// limits, it will). Eventually, we'll be able to wait for a specified amount
// of data to become available.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -1545,7 +1549,7 @@ TYPED_TEST(DataPipeImplTest, AllOrNone) {
if (num_bytes >= 10u * sizeof(int32_t))
break;
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
}
EXPECT_EQ(10u * sizeof(int32_t), num_bytes);
@ -1596,7 +1600,7 @@ TYPED_TEST(DataPipeImplTest, AllOrNone) {
this->ProducerClose();
// Wait.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@ -1686,7 +1690,7 @@ TYPED_TEST(DataPipeImplTest, WrapAround) {
// Wait for data.
// TODO(vtl): (See corresponding TODO in AllOrNone.)
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -1732,7 +1736,7 @@ TYPED_TEST(DataPipeImplTest, WrapAround) {
EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE, result);
}
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
}
EXPECT_EQ(90u, total_num_bytes);
@ -1745,7 +1749,7 @@ TYPED_TEST(DataPipeImplTest, WrapAround) {
if (num_bytes >= 100u)
break;
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
}
EXPECT_EQ(100u, num_bytes);
@ -1823,7 +1827,7 @@ TYPED_TEST(DataPipeImplTest, WriteCloseProducerRead) {
if (num_bytes >= 2u * kTestDataSize)
break;
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
}
EXPECT_EQ(2u * kTestDataSize, num_bytes);
@ -1898,7 +1902,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseWriteReadCloseConsumer) {
// Wait for data.
// TODO(vtl): (See corresponding TODO in AllOrNone.)
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -1924,7 +1928,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseWriteReadCloseConsumer) {
this->ConsumerClose();
// Wait for producer to know that the consumer is closed.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2016,7 +2020,7 @@ TYPED_TEST(DataPipeImplTest, WriteCloseProducerReadNoData) {
// Wait. (Note that once the consumer knows that the producer is closed, it
// must also know about all the data that was sent.)
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@ -2095,7 +2099,7 @@ TYPED_TEST(DataPipeImplTest, WriteReadCloseProducerWaitNoData) {
EXPECT_EQ(kTestDataSize, num_bytes);
// Wait.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -2122,7 +2126,7 @@ TYPED_TEST(DataPipeImplTest, WriteReadCloseProducerWaitNoData) {
// Wait.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
waiter.Wait(test::TinyDeadline(), nullptr));
waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2164,7 +2168,7 @@ TYPED_TEST(DataPipeImplTest, BeginReadCloseProducerWaitEndReadNoData) {
EXPECT_EQ(kTestDataSize, num_bytes);
// Wait.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -2190,7 +2194,7 @@ TYPED_TEST(DataPipeImplTest, BeginReadCloseProducerWaitEndReadNoData) {
this->ProducerClose();
// Wait for producer close to be detected.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2208,7 +2212,7 @@ TYPED_TEST(DataPipeImplTest, BeginReadCloseProducerWaitEndReadNoData) {
// Wait.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
waiter.Wait(test::TinyDeadline(), nullptr));
waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2260,7 +2264,7 @@ TYPED_TEST(DataPipeImplTest, BeginWriteCloseConsumerWaitEndWrite) {
// Note: If we didn't wait for the consumer close to be detected before
// completing the two-phase write, wait might succeed (in the remote cases).
// This is because the first |Awake()| "wins".
EXPECT_EQ(MOJO_RESULT_OK, waiter1.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter1.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&waiter1, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2271,7 +2275,7 @@ TYPED_TEST(DataPipeImplTest, BeginWriteCloseConsumerWaitEndWrite) {
// Wait.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
waiter2.Wait(test::TinyDeadline(), nullptr));
waiter2.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ProducerRemoveAwakable(&waiter2, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
@ -2307,7 +2311,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseMoreInvalidArguments) {
// Wait a bit, to make sure that if a signal were (incorrectly) sent, it'd
// have time to propagate.
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
// Still no data.
num_bytes = 1000u;
@ -2329,7 +2333,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseMoreInvalidArguments) {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, this->ProducerEndWriteData(0u));
// Wait a bit (as above).
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
// Still no data.
num_bytes = 1000u;
@ -2351,7 +2355,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseMoreInvalidArguments) {
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, this->ProducerEndWriteData(0u));
// Wait a bit (as above).
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
// Still no data.
num_bytes = 1000u;
@ -2374,7 +2378,7 @@ TYPED_TEST(DataPipeImplTest, TwoPhaseMoreInvalidArguments) {
// Wait for data.
// TODO(vtl): (See corresponding TODO in AllOrNone.)
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::TinyTimeout(), nullptr));
hss = HandleSignalsState();
this->ConsumerRemoveAwakable(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
@ -2467,7 +2471,7 @@ TYPED_TEST(DataPipeImplTest, WriteCloseProducerTwoPhaseReadAllData) {
if (num_bytes >= kTestDataSize)
break;
test::Sleep(test::EpsilonDeadline());
test::Sleep(test::EpsilonTimeout());
}
EXPECT_EQ(kTestDataSize, num_bytes);

View File

@ -10,6 +10,9 @@
#include "mojo/edk/system/data_pipe.h"
#include "mojo/edk/system/memory.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -6,7 +6,8 @@
#define MOJO_EDK_SYSTEM_DATA_PIPE_PRODUCER_DISPATCHER_H_
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -19,21 +20,20 @@ class DataPipe;
// thread-safe.
class DataPipeProducerDispatcher final : public Dispatcher {
public:
static RefPtr<DataPipeProducerDispatcher> Create() {
static util::RefPtr<DataPipeProducerDispatcher> Create() {
return AdoptRef(new DataPipeProducerDispatcher());
}
// Must be called before any other methods.
void Init(RefPtr<DataPipe>&& data_pipe) MOJO_NOT_THREAD_SAFE;
void Init(util::RefPtr<DataPipe>&& data_pipe) MOJO_NOT_THREAD_SAFE;
// |Dispatcher| public methods:
Type GetType() const override;
// The "opposite" of |SerializeAndClose()|. (Typically this is called by
// |Dispatcher::Deserialize()|.)
static RefPtr<DataPipeProducerDispatcher> Deserialize(Channel* channel,
const void* source,
size_t size);
static util::RefPtr<DataPipeProducerDispatcher>
Deserialize(Channel* channel, const void* source, size_t size);
// Get access to the |DataPipe| for testing.
DataPipe* GetDataPipeForTest();
@ -45,7 +45,8 @@ class DataPipeProducerDispatcher final : public Dispatcher {
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override;
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
override;
MojoResult WriteDataImplNoLock(UserPointer<const void> elements,
UserPointer<uint32_t> num_bytes,
MojoWriteDataFlags flags) override;
@ -73,7 +74,7 @@ class DataPipeProducerDispatcher final : public Dispatcher {
bool IsBusyNoLock() const override;
// This will be null if closed.
RefPtr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex());
util::RefPtr<DataPipe> data_pipe_ MOJO_GUARDED_BY(mutex());
MOJO_DISALLOW_COPY_AND_ASSIGN(DataPipeProducerDispatcher);
};

View File

@ -12,6 +12,9 @@
#include "mojo/edk/system/platform_handle_dispatcher.h"
#include "mojo/edk/system/shared_buffer_dispatcher.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -15,9 +15,10 @@
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/system/handle_signals_state.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_counted.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_counted.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/buffer.h"
#include "mojo/public/c/system/data_pipe.h"
#include "mojo/public/c/system/message_pipe.h"
@ -42,7 +43,7 @@ class ProxyMessagePipeEndpoint;
class TransportData;
class Awakable;
using DispatcherVector = std::vector<RefPtr<Dispatcher>>;
using DispatcherVector = std::vector<util::RefPtr<Dispatcher>>;
namespace test {
@ -56,7 +57,7 @@ DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher);
// object is thread-safe, with its state being protected by a single mutex
// |mutex_|, which is also made available to implementation subclasses (via the
// |mutex()| method).
class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
class Dispatcher : public util::RefCountedThreadSafe<Dispatcher> {
public:
enum class Type {
UNKNOWN = 0,
@ -114,7 +115,7 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
// new handle on success).
MojoResult DuplicateBufferHandle(
UserPointer<const MojoDuplicateBufferHandleOptions> options,
RefPtr<Dispatcher>* new_dispatcher);
util::RefPtr<Dispatcher>* new_dispatcher);
MojoResult MapBuffer(
uint64_t offset,
uint64_t num_bytes,
@ -204,7 +205,7 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
// Deserialization API.
// Note: This "clears" (i.e., reset to the invalid handle) any platform
// handles that it takes ownership of.
static RefPtr<Dispatcher> Deserialize(
static util::RefPtr<Dispatcher> Deserialize(
Channel* channel,
int32_t type,
const void* source,
@ -222,7 +223,8 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
virtual void CancelAllAwakablesNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
virtual void CloseImplNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
virtual RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
virtual util::RefPtr<Dispatcher>
CreateEquivalentDispatcherAndCloseImplNoLock()
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0;
// These are to be overridden by subclasses (if necessary). They are never
@ -261,7 +263,8 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
virtual MojoResult DuplicateBufferHandleImplNoLock(
UserPointer<const MojoDuplicateBufferHandleOptions> options,
RefPtr<Dispatcher>* new_dispatcher) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
util::RefPtr<Dispatcher>* new_dispatcher)
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
virtual MojoResult MapBufferImplNoLock(
uint64_t offset,
uint64_t num_bytes,
@ -308,7 +311,7 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
// handle from being sent over a message pipe (with status "busy").
virtual bool IsBusyNoLock() const MOJO_SHARED_LOCKS_REQUIRED(mutex_);
Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; }
util::Mutex& mutex() const MOJO_LOCK_RETURNED(mutex_) { return mutex_; }
private:
FRIEND_REF_COUNTED_THREAD_SAFE(Dispatcher);
@ -325,7 +328,7 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
// dispatcher will look as though it was closed, but the resource it
// represents will be assigned to the new dispatcher. This must be called
// under the dispatcher's lock.
RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock()
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock()
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// API to serialize dispatchers to a |Channel|, exposed to only
@ -373,7 +376,7 @@ class Dispatcher : public RefCountedThreadSafe<Dispatcher> {
// This protects the following members as well as any state added by
// subclasses.
mutable Mutex mutex_;
mutable util::Mutex mutex_;
bool is_closed_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(Dispatcher);
@ -396,7 +399,8 @@ class DispatcherTransport {
return dispatcher_->IsBusyNoLock();
}
void Close() MOJO_NOT_THREAD_SAFE { dispatcher_->CloseNoLock(); }
RefPtr<Dispatcher> CreateEquivalentDispatcherAndClose() MOJO_NOT_THREAD_SAFE {
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndClose()
MOJO_NOT_THREAD_SAFE {
return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock();
}

View File

@ -7,16 +7,20 @@
#include <memory>
#include <vector>
#include "base/synchronization/waitable_event.h"
#include "base/logging.h"
#include "mojo/edk/embedder/platform_shared_buffer.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test/simple_test_thread.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/test/simple_test_thread.h"
#include "mojo/edk/util/make_unique.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::MakeRefCounted;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -117,7 +121,7 @@ TEST(DispatcherTest, Basic) {
EXPECT_EQ(0u, hss.satisfiable_signals);
}
class ThreadSafetyStressThread : public mojo::test::SimpleTestThread {
class ThreadSafetyStressThread : public test::SimpleTestThread {
public:
enum DispatcherOp {
CLOSE = 0,
@ -136,7 +140,7 @@ class ThreadSafetyStressThread : public mojo::test::SimpleTestThread {
DISPATCHER_OP_COUNT
};
ThreadSafetyStressThread(base::WaitableEvent* event,
ThreadSafetyStressThread(ManualResetWaitableEvent* event,
RefPtr<Dispatcher> dispatcher,
DispatcherOp op)
: event_(event), dispatcher_(dispatcher), op_(op) {
@ -240,7 +244,7 @@ class ThreadSafetyStressThread : public mojo::test::SimpleTestThread {
EXPECT_EQ(0u, hss.satisfiable_signals);
}
base::WaitableEvent* const event_;
ManualResetWaitableEvent* const event_;
const RefPtr<Dispatcher> dispatcher_;
const DispatcherOp op_;
@ -254,8 +258,8 @@ TEST(DispatcherTest, ThreadSafetyStress) {
static const size_t kNumThreads = 100;
for (size_t i = 0; i < kRepeatCount; i++) {
// Manual reset, not initially signalled.
base::WaitableEvent event(true, false);
// Manual reset, not initially signaled.
ManualResetWaitableEvent event;
auto d = MakeRefCounted<TrivialDispatcher>();
{
@ -282,8 +286,8 @@ TEST(DispatcherTest, ThreadSafetyStressNoClose) {
static const size_t kNumThreads = 100;
for (size_t i = 0; i < kRepeatCount; i++) {
// Manual reset, not initially signalled.
base::WaitableEvent event(true, false);
// Manual reset, not initially signaled.
ManualResetWaitableEvent event;
auto d = MakeRefCounted<TrivialDispatcher>();
{

View File

@ -10,6 +10,9 @@
#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/message_in_transit.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -8,8 +8,9 @@
#include <memory>
#include "mojo/edk/system/channel_endpoint_client.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -61,14 +62,14 @@ class EndpointRelayer final : public ChannelEndpointClient {
MOJO_DISALLOW_COPY_AND_ASSIGN(Filter);
};
// Note: Use |MakeRefCounted<EndpointRelayer>()|.
// Note: Use |util::MakeRefCounted<EndpointRelayer>()|.
// Gets the other port number (i.e., 0 -> 1, 1 -> 0).
static unsigned GetPeerPort(unsigned port);
// Initialize this object. This must be called before any other method.
void Init(RefPtr<ChannelEndpoint>&& endpoint0,
RefPtr<ChannelEndpoint>&& endpoint1) MOJO_NOT_THREAD_SAFE;
void Init(util::RefPtr<ChannelEndpoint>&& endpoint0,
util::RefPtr<ChannelEndpoint>&& endpoint1) MOJO_NOT_THREAD_SAFE;
// Sets (or resets) the filter, which can (optionally) handle/filter
// |Type::ENDPOINT_CLIENT| messages (see |Filter| above).
@ -84,8 +85,8 @@ class EndpointRelayer final : public ChannelEndpointClient {
EndpointRelayer();
~EndpointRelayer() override;
Mutex mutex_;
RefPtr<ChannelEndpoint> endpoints_[2] MOJO_GUARDED_BY(mutex_);
util::Mutex mutex_;
util::RefPtr<ChannelEndpoint> endpoints_[2] MOJO_GUARDED_BY(mutex_);
std::unique_ptr<Filter> filter_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(EndpointRelayer);

View File

@ -5,17 +5,20 @@
#include "mojo/edk/system/endpoint_relayer.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "mojo/edk/system/channel_endpoint_id.h"
#include "mojo/edk/system/channel_test_base.h"
#include "mojo/edk/system/message_in_transit_queue.h"
#include "mojo/edk/system/message_in_transit_test_utils.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/test_channel_endpoint_client.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/util/make_unique.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MakeRefCounted;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -90,13 +93,13 @@ class EndpointRelayerTest : public test::ChannelTestBase {
};
TEST_F(EndpointRelayerTest, Basic) {
base::WaitableEvent read_event(true, false);
ManualResetWaitableEvent read_event;
client1b()->SetReadEvent(&read_event);
EXPECT_EQ(0u, client1b()->NumMessages());
EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(12345)));
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
client1b()->SetReadEvent(nullptr);
ASSERT_EQ(1u, client1b()->NumMessages());
@ -111,7 +114,7 @@ TEST_F(EndpointRelayerTest, Basic) {
EXPECT_TRUE(endpoint1b()->EnqueueMessage(test::MakeTestMessage(67890)));
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
client1a()->SetReadEvent(nullptr);
ASSERT_EQ(1u, client1a()->NumMessages());
@ -127,10 +130,10 @@ TEST_F(EndpointRelayerTest, MultipleMessages) {
EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(4)));
EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5)));
base::WaitableEvent read_event(true, false);
ManualResetWaitableEvent read_event;
client1b()->SetReadEvent(&read_event);
for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) {
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
read_event.Reset();
}
client1b()->SetReadEvent(nullptr);
@ -198,10 +201,10 @@ TEST_F(EndpointRelayerTest, Filter) {
EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(1003)));
EXPECT_TRUE(endpoint1a()->EnqueueMessage(test::MakeTestMessage(5)));
base::WaitableEvent read_event(true, false);
ManualResetWaitableEvent read_event;
client1b()->SetReadEvent(&read_event);
for (size_t i = 0; client1b()->NumMessages() < 5 && i < 5; i++) {
EXPECT_TRUE(read_event.TimedWait(TestTimeouts::tiny_timeout()));
EXPECT_FALSE(read_event.WaitWithTimeout(test::TinyTimeout()));
read_event.Reset();
}
client1b()->SetReadEvent(nullptr);

View File

@ -11,6 +11,8 @@
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/dispatcher.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -9,7 +9,7 @@
#include <utility>
#include <vector>
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
@ -20,7 +20,7 @@ class Core;
class Dispatcher;
class DispatcherTransport;
using DispatcherVector = std::vector<RefPtr<Dispatcher>>;
using DispatcherVector = std::vector<util::RefPtr<Dispatcher>>;
// Test-only function (defined/used in embedder/test_embedder.cc). Declared here
// so it can be friended.
@ -46,7 +46,7 @@ class HandleTable {
// handle.
// WARNING: For efficiency, this returns a dumb pointer. If you're going to
// use the result outside |Core|'s lock, you MUST take a reference (e.g., by
// storing the result inside a |RefPtr|).
// storing the result inside a |util::RefPtr|).
Dispatcher* GetDispatcher(MojoHandle handle);
// On success, gets the dispatcher for a given handle (which should not be
@ -55,7 +55,7 @@ class HandleTable {
// |MOJO_RESULT_INVALID_ARGUMENT| if there's no dispatcher for the given
// handle or |MOJO_RESULT_BUSY| if the handle is marked as busy.)
MojoResult GetAndRemoveDispatcher(MojoHandle handle,
RefPtr<Dispatcher>* dispatcher);
util::RefPtr<Dispatcher>* dispatcher);
// Adds a dispatcher (which must be valid), returning the handle for it.
// Returns |MOJO_HANDLE_INVALID| on failure (if the handle table is full).
@ -118,16 +118,16 @@ class HandleTable {
// closed (or learning about this too late).
struct Entry {
Entry();
explicit Entry(RefPtr<Dispatcher>&& dispatcher);
explicit Entry(util::RefPtr<Dispatcher>&& dispatcher);
~Entry();
RefPtr<Dispatcher> dispatcher;
util::RefPtr<Dispatcher> dispatcher;
bool busy;
};
using HandleToEntryMap = std::unordered_map<MojoHandle, Entry>;
// Adds the given dispatcher to the handle table, not doing any size checks.
MojoHandle AddDispatcherNoSizeCheck(RefPtr<Dispatcher>&& dispatcher);
MojoHandle AddDispatcherNoSizeCheck(util::RefPtr<Dispatcher>&& dispatcher);
HandleToEntryMap handle_to_entry_map_;
MojoHandle next_handle_; // Invariant: never |MOJO_HANDLE_INVALID|.

View File

@ -13,6 +13,10 @@
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/remote_producer_data_pipe_impl.h"
using mojo::util::MakeRefCounted;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -9,8 +9,9 @@
#include "mojo/edk/system/channel_endpoint_client.h"
#include "mojo/edk/system/message_in_transit_queue.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
struct MojoCreateDataPipeOptions;
@ -27,16 +28,16 @@ class MessagePipe;
// |MessagePipe|s or |DataPipe|s.
class IncomingEndpoint final : public ChannelEndpointClient {
public:
// Note: Use |MakeRefCounted<IncomingEndpoint>()|.
// Note: Use |util::MakeRefCounted<IncomingEndpoint>()|.
// Must be called before any other method.
RefPtr<ChannelEndpoint> Init() MOJO_NOT_THREAD_SAFE;
util::RefPtr<ChannelEndpoint> Init() MOJO_NOT_THREAD_SAFE;
RefPtr<MessagePipe> ConvertToMessagePipe();
RefPtr<DataPipe> ConvertToDataPipeProducer(
util::RefPtr<MessagePipe> ConvertToMessagePipe();
util::RefPtr<DataPipe> ConvertToDataPipeProducer(
const MojoCreateDataPipeOptions& validated_options,
size_t consumer_num_bytes);
RefPtr<DataPipe> ConvertToDataPipeConsumer(
util::RefPtr<DataPipe> ConvertToDataPipeConsumer(
const MojoCreateDataPipeOptions& validated_options);
// Must be called before destroying this object if |ConvertToMessagePipe()|
@ -53,8 +54,8 @@ class IncomingEndpoint final : public ChannelEndpointClient {
IncomingEndpoint();
~IncomingEndpoint() override;
Mutex mutex_;
RefPtr<ChannelEndpoint> endpoint_ MOJO_GUARDED_BY(mutex_);
util::Mutex mutex_;
util::RefPtr<ChannelEndpoint> endpoint_ MOJO_GUARDED_BY(mutex_);
MessageInTransitQueue message_queue_ MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(IncomingEndpoint);

View File

@ -14,6 +14,8 @@
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/slave_connection_manager.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -9,7 +9,6 @@
#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "mojo/edk/embedder/platform_task_runner.h"
#include "mojo/edk/embedder/process_type.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
@ -17,7 +16,7 @@
#include "mojo/edk/system/channel_id.h"
#include "mojo/edk/system/connection_identifier.h"
#include "mojo/edk/system/process_identifier.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -100,7 +99,7 @@ class IPCSupport {
//
// TODO(vtl): Add some more channel management functionality to this class.
// Maybe make this callback interface more sane.
RefPtr<MessagePipeDispatcher> ConnectToSlave(
util::RefPtr<MessagePipeDispatcher> ConnectToSlave(
const ConnectionIdentifier& connection_id,
embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
@ -116,7 +115,7 @@ class IPCSupport {
// |ConnectToSlave()|.
//
// TODO(vtl): |ConnectToSlave()|'s channel management TODO also applies here.
RefPtr<MessagePipeDispatcher> ConnectToMaster(
util::RefPtr<MessagePipeDispatcher> ConnectToMaster(
const ConnectionIdentifier& connection_id,
const base::Closure& callback,
embedder::PlatformTaskRunnerRefPtr callback_thread_task_runner,

View File

@ -9,10 +9,7 @@
#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/test_timeouts.h"
#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/simple_platform_support.h"
@ -23,18 +20,20 @@
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
#include "mojo/edk/system/process_identifier.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/test_command_line.h"
#include "mojo/edk/system/test/test_io_thread.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/test/multiprocess_test_helper.h"
#include "mojo/edk/test/test_io_thread.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/edk/util/command_line.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
using test::TestIOThread;
namespace system {
namespace {
@ -58,7 +57,7 @@ void TestWriteReadMessage(MessagePipeDispatcher* write_mp,
MOJO_WRITE_MESSAGE_FLAG_NONE));
// Wait for it to arrive.
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), nullptr));
EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionTimeout(), nullptr));
read_mp->RemoveAwakable(&waiter, nullptr);
// Read the message from the read end.
@ -102,7 +101,7 @@ RefPtr<MessagePipeDispatcher> SendMessagePipeDispatcher(
mp_to_send = nullptr;
// Wait for it to arrive.
CHECK_EQ(waiter.Wait(test::ActionDeadline(), nullptr), MOJO_RESULT_OK);
CHECK_EQ(waiter.Wait(test::ActionTimeout(), nullptr), MOJO_RESULT_OK);
read_mp->RemoveAwakable(&waiter, nullptr);
// Read the message from the read end.
@ -121,14 +120,13 @@ RefPtr<MessagePipeDispatcher> SendMessagePipeDispatcher(
class TestMasterProcessDelegate : public embedder::MasterProcessDelegate {
public:
TestMasterProcessDelegate()
: on_slave_disconnect_event_(false, false) {} // Auto reset.
TestMasterProcessDelegate() {}
~TestMasterProcessDelegate() override {}
// Warning: There's only one slave disconnect event (which resets
// automatically).
bool TryWaitForOnSlaveDisconnect() {
return on_slave_disconnect_event_.TimedWait(TestTimeouts::action_timeout());
return !on_slave_disconnect_event_.WaitWithTimeout(test::ActionTimeout());
}
private:
@ -139,7 +137,7 @@ class TestMasterProcessDelegate : public embedder::MasterProcessDelegate {
on_slave_disconnect_event_.Signal();
}
base::WaitableEvent on_slave_disconnect_event_;
AutoResetWaitableEvent on_slave_disconnect_event_;
MOJO_DISALLOW_COPY_AND_ASSIGN(TestMasterProcessDelegate);
};
@ -161,13 +159,12 @@ class TestSlaveProcessDelegate : public embedder::SlaveProcessDelegate {
// Represents the master's side of its connection to a slave.
class TestSlaveConnection {
public:
TestSlaveConnection(TestIOThread* test_io_thread,
TestSlaveConnection(test::TestIOThread* test_io_thread,
IPCSupport* master_ipc_support)
: test_io_thread_(test_io_thread),
master_ipc_support_(master_ipc_support),
connection_id_(master_ipc_support_->GenerateConnectionIdentifier()),
slave_id_(kInvalidProcessIdentifier),
event_(true, false) {}
slave_id_(kInvalidProcessIdentifier) {}
~TestSlaveConnection() {}
// After this is called, |ShutdownChannelToSlave()| must be called (possibly
@ -177,7 +174,8 @@ class TestSlaveConnection {
// Note: |ChannelId|s and |ProcessIdentifier|s are interchangeable.
RefPtr<MessagePipeDispatcher> mp = master_ipc_support_->ConnectToSlave(
connection_id_, nullptr, channel_pair.PassServerHandle(),
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)),
base::Bind(&ManualResetWaitableEvent::Signal,
base::Unretained(&event_)),
nullptr, &slave_id_);
EXPECT_TRUE(mp);
EXPECT_NE(slave_id_, kInvalidProcessIdentifier);
@ -187,7 +185,7 @@ class TestSlaveConnection {
}
void WaitForChannelToSlave() {
EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout()));
EXPECT_FALSE(event_.WaitWithTimeout(test::ActionTimeout()));
}
void ShutdownChannelToSlave() {
@ -207,13 +205,13 @@ class TestSlaveConnection {
const ConnectionIdentifier& connection_id() const { return connection_id_; }
private:
TestIOThread* const test_io_thread_;
test::TestIOThread* const test_io_thread_;
IPCSupport* const master_ipc_support_;
const ConnectionIdentifier connection_id_;
// The master's message pipe dispatcher.
RefPtr<MessagePipeDispatcher> message_pipe_;
ProcessIdentifier slave_id_;
base::WaitableEvent event_;
ManualResetWaitableEvent event_;
embedder::ScopedPlatformHandle slave_platform_handle_;
MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlaveConnection);
@ -225,7 +223,7 @@ class TestSlave {
public:
// Note: Before destruction, |ShutdownIPCSupport()| must be called.
TestSlave(embedder::PlatformSupport* platform_support,
TestIOThread* test_io_thread,
test::TestIOThread* test_io_thread,
embedder::ScopedPlatformHandle platform_handle)
: test_io_thread_(test_io_thread),
slave_ipc_support_(platform_support,
@ -233,8 +231,7 @@ class TestSlave {
test_io_thread->task_runner(),
&slave_process_delegate_,
test_io_thread->task_runner(),
platform_handle.Pass()),
event_(true, false) {}
platform_handle.Pass()) {}
~TestSlave() {}
// After this is called, |ShutdownChannelToMaster()| must be called (possibly
@ -243,8 +240,8 @@ class TestSlave {
const ConnectionIdentifier& connection_id) {
ProcessIdentifier master_id = kInvalidProcessIdentifier;
RefPtr<MessagePipeDispatcher> mp = slave_ipc_support_.ConnectToMaster(
connection_id,
base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event_)),
connection_id, base::Bind(&ManualResetWaitableEvent::Signal,
base::Unretained(&event_)),
nullptr, &master_id);
EXPECT_TRUE(mp);
EXPECT_EQ(kMasterProcessIdentifier, master_id);
@ -252,7 +249,7 @@ class TestSlave {
}
void WaitForChannelToMaster() {
EXPECT_TRUE(event_.TimedWait(TestTimeouts::action_timeout()));
EXPECT_FALSE(event_.WaitWithTimeout(test::ActionTimeout()));
}
void ShutdownChannelToMaster() {
@ -273,10 +270,10 @@ class TestSlave {
}
private:
TestIOThread* const test_io_thread_;
test::TestIOThread* const test_io_thread_;
TestSlaveProcessDelegate slave_process_delegate_;
IPCSupport slave_ipc_support_;
base::WaitableEvent event_;
ManualResetWaitableEvent event_;
MOJO_DISALLOW_COPY_AND_ASSIGN(TestSlave);
};
@ -285,7 +282,7 @@ class TestSlave {
class TestSlaveSetup {
public:
TestSlaveSetup(embedder::SimplePlatformSupport* platform_support,
TestIOThread* test_io_thread,
test::TestIOThread* test_io_thread,
TestMasterProcessDelegate* master_process_delegate,
IPCSupport* master_ipc_support)
: platform_support_(platform_support),
@ -351,7 +348,7 @@ class TestSlaveSetup {
private:
embedder::SimplePlatformSupport* const platform_support_;
TestIOThread* const test_io_thread_;
test::TestIOThread* const test_io_thread_;
TestMasterProcessDelegate* const master_process_delegate_;
IPCSupport* const master_ipc_support_;
@ -368,7 +365,7 @@ class IPCSupportTest : public testing::Test {
public:
// Note: Run master process delegate methods on the I/O thread.
IPCSupportTest()
: test_io_thread_(TestIOThread::StartMode::AUTO),
: test_io_thread_(test::TestIOThread::StartMode::AUTO),
master_ipc_support_(&platform_support_,
embedder::ProcessType::MASTER,
test_io_thread_.task_runner(),
@ -394,7 +391,7 @@ class IPCSupportTest : public testing::Test {
embedder::SimplePlatformSupport& platform_support() {
return platform_support_;
}
TestIOThread& test_io_thread() { return test_io_thread_; }
test::TestIOThread& test_io_thread() { return test_io_thread_; }
TestMasterProcessDelegate& master_process_delegate() {
return master_process_delegate_;
}
@ -402,7 +399,7 @@ class IPCSupportTest : public testing::Test {
private:
embedder::SimplePlatformSupport platform_support_;
TestIOThread test_io_thread_;
test::TestIOThread test_io_thread_;
// All tests require a master.
TestMasterProcessDelegate master_process_delegate_;
@ -436,7 +433,7 @@ TEST_F(IPCSupportTest, MasterSlave) {
// A message was sent through the message pipe, |Channel|s must have been
// established on both sides. The events have thus almost certainly been
// signalled, but we'll wait just to be sure.
// signaled, but we'll wait just to be sure.
s->slave_connection()->WaitForChannelToSlave();
s->slave()->WaitForChannelToMaster();
@ -675,7 +672,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) {
ASSERT_TRUE(client_platform_handle.is_valid());
embedder::SimplePlatformSupport platform_support;
TestIOThread test_io_thread(TestIOThread::StartMode::AUTO);
test::TestIOThread test_io_thread(test::TestIOThread::StartMode::AUTO);
TestSlaveProcessDelegate slave_process_delegate;
// Note: Run process delegate methods on the I/O thread.
IPCSupport ipc_support(&platform_support, embedder::ProcessType::SLAVE,
@ -683,12 +680,12 @@ MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) {
test_io_thread.task_runner(),
client_platform_handle.Pass());
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag));
std::string connection_id_string;
ASSERT_TRUE(test::GetTestCommandLine()->GetOptionValue(
kConnectionIdFlag, &connection_id_string));
bool ok = false;
ConnectionIdentifier connection_id = ConnectionIdentifier::FromString(
command_line.GetSwitchValueASCII(kConnectionIdFlag), &ok);
ConnectionIdentifier connection_id =
ConnectionIdentifier::FromString(connection_id_string, &ok);
ASSERT_TRUE(ok);
embedder::ScopedPlatformHandle second_platform_handle =

View File

@ -25,6 +25,8 @@
#include "mojo/edk/system/remote_producer_data_pipe_impl.h"
#include "mojo/edk/util/make_unique.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -13,7 +13,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "mojo/edk/embedder/master_process_delegate.h"
#include "mojo/edk/embedder/platform_channel_pair.h"
#include "mojo/edk/embedder/platform_handle.h"
@ -22,9 +21,12 @@
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/transport_data.h"
#include "mojo/edk/system/waitable_event.h"
#include "mojo/edk/util/make_unique.h"
#include "mojo/public/cpp/system/macros.h"
using mojo::util::MutexLocker;
namespace mojo {
namespace system {
@ -371,7 +373,7 @@ ProcessIdentifier MasterConnectionManager::AddSlave(
// We have to wait for the task to be executed, in case someone calls
// |AddSlave()| followed immediately by |Shutdown()|.
base::WaitableEvent event(false, false);
AutoResetWaitableEvent event;
private_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&MasterConnectionManager::AddSlaveOnPrivateThread,
@ -671,7 +673,7 @@ void MasterConnectionManager::AddSlaveOnPrivateThread(
embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
ProcessIdentifier slave_process_identifier,
base::WaitableEvent* event) {
AutoResetWaitableEvent* event) {
DCHECK(platform_handle.is_valid());
DCHECK(event);
AssertOnPrivateThread();

View File

@ -9,17 +9,16 @@
#include <unordered_map>
#include "base/memory/ref_counted.h"
#include "base/threading/thread.h"
#include "mojo/edk/embedder/platform_task_runner.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/connection_manager.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace base {
class TaskRunner;
class WaitableEvent;
}
namespace mojo {
@ -31,6 +30,8 @@ using SlaveInfo = void*;
namespace system {
class AutoResetWaitableEvent;
// The |ConnectionManager| implementation for the master process.
//
// This class is thread-safe (except that no public methods may be called from
@ -115,7 +116,7 @@ class MasterConnectionManager final : public ConnectionManager {
void AddSlaveOnPrivateThread(embedder::SlaveInfo slave_info,
embedder::ScopedPlatformHandle platform_handle,
ProcessIdentifier slave_process_identifier,
base::WaitableEvent* event);
AutoResetWaitableEvent* event);
// Called by |Helper::OnError()|.
void OnError(ProcessIdentifier process_identifier);
// Posts a call to |master_process_delegate_->OnSlaveDisconnect()|.
@ -147,7 +148,7 @@ class MasterConnectionManager final : public ConnectionManager {
// Note: |mutex_| is not needed in the constructor, |Init()|,
// |Shutdown()|/|ShutdownOnPrivateThread()|, or the destructor
Mutex mutex_;
util::Mutex mutex_;
ProcessIdentifier next_process_identifier_ MOJO_GUARDED_BY(mutex_);

View File

@ -58,8 +58,8 @@ template <typename Type>
class UserPointerWriter;
template <typename Type>
class UserPointerReaderWriter;
template <class Options>
class UserOptionsReader;
template <typename Type>
class UserPointerPartialReader;
// Provides a convenient way to implicitly get null |UserPointer<Type>|s.
struct NullUserPointer {};
@ -75,6 +75,8 @@ class UserPointer {
using NonVoidType = typename internal::VoidToChar<Type>::type;
public:
static_assert(!std::is_volatile<Type>::value, "Type must not be volatile");
// Instead of explicitly using these constructors, you can often use
// |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common
// exception is when you have, e.g., a |char*| and want to get a
@ -235,13 +237,25 @@ class UserPointer {
using Writer = UserPointerWriter<Type>;
using ReaderWriter = UserPointerReaderWriter<Type>;
// This is like |Reader| above, but for partially reading the memory of a
// single object (usually a struct). The pointer it provides will be to a full
// |Type| (no more, no less), with unavailable bytes set to zero.
//
// Note: It isn't safe to just use |UserPointer<const char>::Reader| and
// reinterpret cast the pointer to a struct pointer. Even if before accessing
// a field you check that it's within the available size, the compiler may
// read beyond the extent of the field itself, so long as the read is still
// within the struct.
//
// TODO(vtl): Add writer and reader-writer versions of this if/when necessary.
using PartialReader = UserPointerPartialReader<Type>;
private:
friend class UserPointerReader<Type>;
friend class UserPointerReader<const Type>;
friend class UserPointerWriter<Type>;
friend class UserPointerReaderWriter<Type>;
template <class Options>
friend class UserOptionsReader;
friend class UserPointerPartialReader<Type>;
Type* pointer_;
// Allow copy and assignment.
@ -260,37 +274,29 @@ class UserPointerReader {
using TypeNoConst = typename std::remove_const<Type>::type;
public:
static_assert(!std::is_volatile<Type>::value, "Type must not be volatile");
// Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerReader(UserPointer<const Type> user_pointer, size_t count) {
Init(user_pointer.pointer_, count, true);
UserPointerReader(UserPointer<const TypeNoConst> user_pointer, size_t count) {
Init(user_pointer.pointer_, count);
}
UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) {
Init(user_pointer.pointer_, count, true);
Init(user_pointer.pointer_, count);
}
const Type* GetPointer() const { return buffer_.get(); }
const TypeNoConst* GetPointer() const { return buffer_.get(); }
private:
template <class Options>
friend class UserOptionsReader;
struct NoCheck {};
UserPointerReader(NoCheck,
UserPointer<const Type> user_pointer,
size_t count) {
Init(user_pointer.pointer_, count, false);
}
void Init(const Type* user_pointer, size_t count, bool check) {
void Init(const TypeNoConst* user_pointer, size_t count) {
if (count == 0)
return;
if (check) {
internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
user_pointer, count);
}
internal::CheckUserPointerWithCount<sizeof(TypeNoConst),
MOJO_ALIGNOF(TypeNoConst)>(user_pointer,
count);
buffer_.reset(new TypeNoConst[count]);
memcpy(buffer_.get(), user_pointer, count * sizeof(Type));
memcpy(buffer_.get(), user_pointer, count * sizeof(TypeNoConst));
}
std::unique_ptr<TypeNoConst[]> buffer_;
@ -302,6 +308,9 @@ class UserPointerReader {
template <typename Type>
class UserPointerWriter {
public:
static_assert(!std::is_volatile<Type>::value, "Type must not be volatile");
static_assert(!std::is_const<Type>::value, "Type must not be const");
// Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerWriter(UserPointer<Type> user_pointer, size_t count)
: user_pointer_(user_pointer), count_(count) {
@ -331,6 +340,9 @@ class UserPointerWriter {
template <typename Type>
class UserPointerReaderWriter {
public:
static_assert(!std::is_volatile<Type>::value, "Type must not be volatile");
static_assert(!std::is_const<Type>::value, "Type must not be const");
// Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count)
: user_pointer_(user_pointer), count_(count) {
@ -359,6 +371,47 @@ class UserPointerReaderWriter {
MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter);
};
// Implementation of |UserPointer<Type>::PartialReader|.
template <typename Type>
class UserPointerPartialReader {
private:
using TypeNoConst = typename std::remove_cv<Type>::type;
public:
static_assert(!std::is_volatile<Type>::value, "Type must not be volatile");
// Note: If |count| is zero, |GetPointer()| will always return null.
UserPointerPartialReader(UserPointer<const TypeNoConst> user_pointer,
size_t num_bytes) {
Init(user_pointer.pointer_, num_bytes);
}
UserPointerPartialReader(UserPointer<TypeNoConst> user_pointer,
size_t num_bytes) {
Init(user_pointer.pointer_, num_bytes);
}
const TypeNoConst* GetPointer() const { return &storage_; }
private:
void Init(const TypeNoConst* user_pointer, size_t num_bytes) {
// Check that all |num_bytes| are valid.
internal::CheckUserPointerWithSize<MOJO_ALIGNOF(TypeNoConst)>(user_pointer,
num_bytes);
// But only copy up to |num_bytes|.
if (num_bytes >= sizeof(TypeNoConst))
num_bytes = sizeof(TypeNoConst);
memcpy(&storage_, user_pointer, num_bytes);
memset(reinterpret_cast<char*>(&storage_) + num_bytes, 0,
sizeof(TypeNoConst) - num_bytes);
}
TypeNoConst storage_;
MOJO_DISALLOW_COPY_AND_ASSIGN(UserPointerPartialReader);
};
} // namespace system
} // namespace mojo

View File

@ -19,6 +19,10 @@
#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
#include "mojo/edk/util/make_unique.h"
using mojo::util::MakeRefCounted;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -11,7 +11,6 @@
#include <memory>
#include <vector>
#include "base/memory/ref_counted.h"
#include "mojo/edk/embedder/platform_handle_vector.h"
#include "mojo/edk/system/channel_endpoint_client.h"
#include "mojo/edk/system/dispatcher.h"
@ -19,8 +18,9 @@
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/message_pipe_endpoint.h"
#include "mojo/edk/system/mutex.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/mutex.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/c/system/message_pipe.h"
#include "mojo/public/c/system/types.h"
#include "mojo/public/cpp/system/macros.h"
@ -39,21 +39,21 @@ class MessageInTransitQueue;
class MessagePipe final : public ChannelEndpointClient {
public:
// Creates a |MessagePipe| with two new |LocalMessagePipeEndpoint|s.
static RefPtr<MessagePipe> CreateLocalLocal();
static util::RefPtr<MessagePipe> CreateLocalLocal();
// Creates a |MessagePipe| with a |LocalMessagePipeEndpoint| on port 0 and a
// |ProxyMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the
// (newly-created) |ChannelEndpoint| for the latter.
static RefPtr<MessagePipe> CreateLocalProxy(
RefPtr<ChannelEndpoint>* channel_endpoint);
static util::RefPtr<MessagePipe> CreateLocalProxy(
util::RefPtr<ChannelEndpoint>* channel_endpoint);
// Similar to |CreateLocalProxy()|, except that it'll do so from an existing
// |ChannelEndpoint| (whose |ReplaceClient()| it'll call) and take
// |message_queue|'s contents as already-received incoming messages. If
// |channel_endpoint| is null, this will create a "half-open" message pipe.
static RefPtr<MessagePipe> CreateLocalProxyFromExisting(
static util::RefPtr<MessagePipe> CreateLocalProxyFromExisting(
MessageInTransitQueue* message_queue,
RefPtr<ChannelEndpoint>&& channel_endpoint);
util::RefPtr<ChannelEndpoint>&& channel_endpoint);
// Creates a |MessagePipe| with a |ProxyMessagePipeEndpoint| on port 0 and a
// |LocalMessagePipeEndpoint| on port 1. |*channel_endpoint| is set to the
@ -61,8 +61,8 @@ class MessagePipe final : public ChannelEndpointClient {
// Note: This is really only needed in tests (outside of tests, this
// configuration arises from a local message pipe having its port 0
// "converted" using |ConvertLocalToProxy()|).
static RefPtr<MessagePipe> CreateProxyLocal(
RefPtr<ChannelEndpoint>* channel_endpoint);
static util::RefPtr<MessagePipe> CreateProxyLocal(
util::RefPtr<ChannelEndpoint>* channel_endpoint);
// Gets the other port number (i.e., 0 -> 1, 1 -> 0).
static unsigned GetPeerPort(unsigned port);
@ -73,7 +73,7 @@ class MessagePipe final : public ChannelEndpointClient {
static bool Deserialize(Channel* channel,
const void* source,
size_t size,
RefPtr<MessagePipe>* message_pipe,
util::RefPtr<MessagePipe>* message_pipe,
unsigned* port);
// Gets the type of the endpoint (used for assertions, etc.).
@ -138,7 +138,7 @@ class MessagePipe final : public ChannelEndpointClient {
std::vector<DispatcherTransport>* transports)
MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
mutable Mutex mutex_;
mutable util::Mutex mutex_;
std::unique_ptr<MessagePipeEndpoint> endpoints_[2] MOJO_GUARDED_BY(mutex_);
MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipe);

View File

@ -14,6 +14,8 @@
#include "mojo/edk/system/options_validation.h"
#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -7,7 +7,8 @@
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -26,7 +27,7 @@ class MessagePipeDispatcher final : public Dispatcher {
// this is exposed directly for testing convenience.)
static const MojoCreateMessagePipeOptions kDefaultCreateOptions;
static RefPtr<MessagePipeDispatcher> Create(
static util::RefPtr<MessagePipeDispatcher> Create(
const MojoCreateMessagePipeOptions& /*validated_options*/) {
return AdoptRef(new MessagePipeDispatcher());
}
@ -41,7 +42,7 @@ class MessagePipeDispatcher final : public Dispatcher {
MojoCreateMessagePipeOptions* out_options);
// Must be called before any other methods. (This method is not thread-safe.)
void Init(RefPtr<MessagePipe>&& message_pipe,
void Init(util::RefPtr<MessagePipe>&& message_pipe,
unsigned port) MOJO_NOT_THREAD_SAFE;
// |Dispatcher| public methods:
@ -52,14 +53,14 @@ class MessagePipeDispatcher final : public Dispatcher {
// the message pipe, port 0).
// TODO(vtl): This currently uses |kDefaultCreateOptions|, which is okay since
// there aren't any options, but eventually options should be plumbed through.
static RefPtr<MessagePipeDispatcher> CreateRemoteMessagePipe(
RefPtr<ChannelEndpoint>* channel_endpoint);
static util::RefPtr<MessagePipeDispatcher> CreateRemoteMessagePipe(
util::RefPtr<ChannelEndpoint>* channel_endpoint);
// The "opposite" of |SerializeAndClose()|. (Typically this is called by
// |Dispatcher::Deserialize()|.)
static RefPtr<MessagePipeDispatcher> Deserialize(Channel* channel,
const void* source,
size_t size);
static util::RefPtr<MessagePipeDispatcher> Deserialize(Channel* channel,
const void* source,
size_t size);
private:
friend class MessagePipeDispatcherTransport;
@ -78,7 +79,8 @@ class MessagePipeDispatcher final : public Dispatcher {
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override;
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
override;
MojoResult WriteMessageImplNoLock(
UserPointer<const void> bytes,
uint32_t num_bytes,
@ -108,7 +110,7 @@ class MessagePipeDispatcher final : public Dispatcher {
MOJO_NOT_THREAD_SAFE;
// This will be null if closed.
RefPtr<MessagePipe> message_pipe_ MOJO_GUARDED_BY(mutex());
util::RefPtr<MessagePipe> message_pipe_ MOJO_GUARDED_BY(mutex());
unsigned port_ MOJO_GUARDED_BY(mutex());
MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);

View File

@ -3,7 +3,7 @@
// found in the LICENSE file.
// NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
// heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to
// heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
// increase tolerance and reduce observed flakiness (though doing so reduces the
// meaningfulness of the test).
@ -17,15 +17,20 @@
#include <vector>
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/random.h"
#include "mojo/edk/system/test/simple_test_thread.h"
#include "mojo/edk/system/test/sleep.h"
#include "mojo/edk/system/test/stopwatch.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waiter.h"
#include "mojo/edk/system/waiter_test_utils.h"
#include "mojo/edk/test/simple_test_thread.h"
#include "mojo/edk/util/make_unique.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -77,7 +82,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_OK, w.Wait(MOJO_DEADLINE_INDEFINITE, &context));
EXPECT_EQ(1u, context);
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline());
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
hss = HandleSignalsState();
d0->RemoveAwakable(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
@ -110,7 +115,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, w.Wait(0, nullptr));
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline());
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
hss = HandleSignalsState();
d0->RemoveAwakable(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
@ -122,10 +127,10 @@ TEST(MessagePipeDispatcherTest, Basic) {
d0->AddAwakable(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr));
stopwatch.Start();
EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
w.Wait(2 * test::EpsilonDeadline(), nullptr));
w.Wait(2 * test::EpsilonTimeout(), nullptr));
MojoDeadline elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline());
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
hss = HandleSignalsState();
d0->RemoveAwakable(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
@ -140,7 +145,7 @@ TEST(MessagePipeDispatcherTest, Basic) {
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
// It should be signaled.
EXPECT_EQ(MOJO_RESULT_OK, w.Wait(test::TinyDeadline(), &context));
EXPECT_EQ(MOJO_RESULT_OK, w.Wait(test::TinyTimeout(), &context));
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
d0->RemoveAwakable(&w, &hss);
@ -371,7 +376,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
&context, &hss);
stopwatch.Start();
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
// Wake it up by writing to |d0|.
buffer[0] = 123456789;
EXPECT_EQ(MOJO_RESULT_OK,
@ -379,8 +384,8 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
nullptr, MOJO_WRITE_MESSAGE_FLAG_NONE));
} // Joins the thread.
elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline());
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_OK, result);
EXPECT_EQ(1u, context);
@ -396,7 +401,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
stopwatch.Start();
thread.Start();
} // Joins the thread.
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonDeadline());
EXPECT_LT(stopwatch.Elapsed(), test::EpsilonTimeout());
EXPECT_FALSE(did_wait);
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
@ -421,12 +426,12 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
&context, &hss);
stopwatch.Start();
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
} // Joins the thread.
elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline());
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
EXPECT_EQ(3u, context);
@ -455,12 +460,12 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
&context, &hss);
stopwatch.Start();
thread.Start();
test::Sleep(2 * test::EpsilonDeadline());
test::Sleep(2 * test::EpsilonTimeout());
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
} // Joins the thread.
elapsed = stopwatch.Elapsed();
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonDeadline());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonDeadline());
EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
EXPECT_EQ(4u, context);
@ -475,7 +480,7 @@ TEST(MessagePipeDispatcherTest, BasicThreaded) {
const size_t kMaxMessageSize = 2000;
class WriterThread : public mojo::test::SimpleTestThread {
class WriterThread : public test::SimpleTestThread {
public:
// |*messages_written| and |*bytes_written| belong to the thread while it's
// alive.
@ -525,7 +530,7 @@ class WriterThread : public mojo::test::SimpleTestThread {
MOJO_DISALLOW_COPY_AND_ASSIGN(WriterThread);
};
class ReaderThread : public mojo::test::SimpleTestThread {
class ReaderThread : public test::SimpleTestThread {
public:
// |*messages_read| and |*bytes_read| belong to the thread while it's alive.
ReaderThread(RefPtr<Dispatcher> read_dispatcher,

View File

@ -10,7 +10,6 @@
#include <memory>
#include <vector>
#include "base/memory/ref_counted.h"
#include "mojo/edk/system/dispatcher.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/message_in_transit.h"

View File

@ -3,30 +3,27 @@
// found in the LICENSE file.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/test/perf_time_logger.h"
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/local_message_pipe_endpoint.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/message_pipe_test_utils.h"
#include "mojo/edk/system/proxy_message_pipe_endpoint.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/perf_log.h"
#include "mojo/edk/system/test/stopwatch.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -73,12 +70,12 @@ class MultiprocessMessagePipePerfTest
std::string test_name =
base::StringPrintf("IPC_Perf_%dx_%u", message_count_,
static_cast<unsigned>(message_size_));
base::PerfTimeLogger logger(test_name.c_str());
test::Stopwatch stopwatch;
stopwatch.Start();
for (int i = 0; i < message_count_; ++i)
WriteWaitThenRead(mp);
logger.Done();
test::LogPerfResult(test_name.c_str(), stopwatch.Elapsed() / 1000.0, "ms");
}
private:
@ -86,7 +83,8 @@ class MultiprocessMessagePipePerfTest
size_t message_size_;
std::string payload_;
std::string read_buffer_;
std::unique_ptr<base::PerfTimeLogger> perf_logger_;
MOJO_DISALLOW_COPY_AND_ASSIGN(MultiprocessMessagePipePerfTest);
};
// For each message received, sends a reply message with the same contents

View File

@ -10,9 +10,13 @@
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/channel_endpoint.h"
#include "mojo/edk/system/message_pipe.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/sleep.h"
#include "mojo/edk/system/test/timeouts.h"
#include "mojo/edk/system/waiter.h"
using mojo::util::MakeRefCounted;
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace test {
@ -37,7 +41,7 @@ MojoResult WaitIfNecessary(MessagePipe* mp,
ChannelThread::ChannelThread(embedder::PlatformSupport* platform_support)
: platform_support_(platform_support),
test_io_thread_(mojo::test::TestIOThread::StartMode::MANUAL) {}
test_io_thread_(TestIOThread::StartMode::MANUAL) {}
ChannelThread::~ChannelThread() {
Stop();
@ -58,7 +62,7 @@ void ChannelThread::Stop() {
// TODO(vtl): Remove this once |Channel| has a
// |FlushWriteBufferAndShutdown()| (or whatever).
while (!channel_->IsWriteBufferEmpty())
test::Sleep(test::DeadlineFromMilliseconds(20));
test::Sleep(test::EpsilonTimeout());
test_io_thread_.PostTaskAndWait(base::Bind(
&ChannelThread::ShutdownChannelOnIOThread, base::Unretained(this)));

View File

@ -7,10 +7,9 @@
#include "mojo/edk/embedder/simple_platform_support.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/system/test/test_io_thread.h"
#include "mojo/edk/test/multiprocess_test_helper.h"
#include "mojo/edk/test/test_io_thread.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -32,19 +31,19 @@ class ChannelThread {
~ChannelThread();
void Start(embedder::ScopedPlatformHandle platform_handle,
RefPtr<ChannelEndpoint>&& channel_endpoint);
util::RefPtr<ChannelEndpoint>&& channel_endpoint);
void Stop();
private:
// TODO(vtl): |channel_endpoint| should be an rvalue reference, but that
// doesn't currently work correctly with base::Bind.
void InitChannelOnIOThread(embedder::ScopedPlatformHandle platform_handle,
RefPtr<ChannelEndpoint> channel_endpoint);
util::RefPtr<ChannelEndpoint> channel_endpoint);
void ShutdownChannelOnIOThread();
embedder::PlatformSupport* const platform_support_;
mojo::test::TestIOThread test_io_thread_;
RefPtr<Channel> channel_;
TestIOThread test_io_thread_;
util::RefPtr<Channel> channel_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ChannelThread);
};
@ -56,7 +55,7 @@ class MultiprocessMessagePipeTestBase : public testing::Test {
~MultiprocessMessagePipeTestBase() override;
protected:
void Init(RefPtr<ChannelEndpoint>&& ep);
void Init(util::RefPtr<ChannelEndpoint>&& ep);
embedder::PlatformSupport* platform_support() { return &platform_support_; }
mojo::test::MultiprocessTestHelper* helper() { return &helper_; }

View File

@ -22,14 +22,15 @@
#include "mojo/edk/system/message_pipe_test_utils.h"
#include "mojo/edk/system/platform_handle_dispatcher.h"
#include "mojo/edk/system/raw_channel.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/shared_buffer_dispatcher.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/edk/test/scoped_test_dir.h"
#include "mojo/edk/system/test/scoped_test_dir.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/scoped_file.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
@ -338,7 +339,7 @@ TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) {
MOJO_WRITE_MESSAGE_FLAG_NONE));
transport.End();
dispatcher->AssertHasOneRef();
EXPECT_TRUE(dispatcher->HasOneRef());
dispatcher = nullptr;
// Wait for a message from the child.
@ -426,7 +427,7 @@ MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) {
RefPtr<PlatformHandleDispatcher> dispatcher(
static_cast<PlatformHandleDispatcher*>(dispatchers[i].get()));
embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle().Pass();
embedder::ScopedPlatformHandle h = dispatcher->PassPlatformHandle();
CHECK(h.is_valid());
dispatcher->Close();
@ -447,7 +448,7 @@ class MultiprocessMessagePipeTestWithPipeCount
public testing::WithParamInterface<size_t> {};
TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
mojo::test::ScopedTestDir test_dir;
test::ScopedTestDir test_dir;
helper()->StartChild("CheckPlatformHandleFile");
@ -468,7 +469,7 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
auto dispatcher =
PlatformHandleDispatcher::Create(embedder::ScopedPlatformHandle(
mojo::test::PlatformHandleFromFILE(fp.Pass())));
mojo::test::PlatformHandleFromFILE(std::move(fp))));
dispatchers.push_back(dispatcher);
DispatcherTransport transport(
test::DispatcherTryStartTransport(dispatcher.get()));
@ -485,7 +486,7 @@ TEST_P(MultiprocessMessagePipeTestWithPipeCount, PlatformHandlePassing) {
for (size_t i = 0; i < pipe_count; ++i) {
transports[i].End();
dispatchers[i]->AssertHasOneRef();
EXPECT_TRUE(dispatchers[i]->HasOneRef());
}
dispatchers.clear();

View File

@ -1,38 +0,0 @@
// Copyright 2014 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/edk/system/mutex.h"
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
#include "base/logging.h"
namespace mojo {
namespace system {
Mutex::Mutex() : lock_() {
}
Mutex::~Mutex() {
DCHECK(owning_thread_ref_.is_null());
}
void Mutex::AssertHeld() const {
DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef());
}
void Mutex::CheckHeldAndUnmark() {
DCHECK(owning_thread_ref_ == base::PlatformThread::CurrentRef());
owning_thread_ref_ = base::PlatformThreadRef();
}
void Mutex::CheckUnheldAndMark() {
DCHECK(owning_thread_ref_.is_null());
owning_thread_ref_ = base::PlatformThread::CurrentRef();
}
} // namespace system
} // namespace mojo
#endif // !NDEBUG || DCHECK_ALWAYS_ON

View File

@ -1,92 +0,0 @@
// Copyright 2015 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.
// A mutex class, with support for thread annotations.
//
// TODO(vtl): Currently, this is a fork of Chromium's
// base/synchronization/lock.h (with names changed and minor modifications; it
// still cheats and uses Chromium's lock_impl.*), but eventually we'll want our
// own and, e.g., add support for non-exclusive (reader) locks.
#ifndef MOJO_EDK_SYSTEM_MUTEX_H_
#define MOJO_EDK_SYSTEM_MUTEX_H_
#include "base/synchronization/lock_impl.h"
#include "base/threading/platform_thread.h"
#include "mojo/edk/system/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
namespace system {
// Mutex -----------------------------------------------------------------------
class MOJO_LOCKABLE Mutex {
public:
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
Mutex() : lock_() {}
~Mutex() {}
void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() { lock_.Lock(); }
void Unlock() MOJO_UNLOCK_FUNCTION() { lock_.Unlock(); }
bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) { return lock_.Try(); }
void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK() {}
#else
Mutex();
~Mutex();
void Lock() MOJO_EXCLUSIVE_LOCK_FUNCTION() {
lock_.Lock();
CheckUnheldAndMark();
}
void Unlock() MOJO_UNLOCK_FUNCTION() {
CheckHeldAndUnmark();
lock_.Unlock();
}
bool TryLock() MOJO_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
bool rv = lock_.Try();
if (rv)
CheckUnheldAndMark();
return rv;
}
void AssertHeld() const MOJO_ASSERT_EXCLUSIVE_LOCK();
#endif // NDEBUG && !DCHECK_ALWAYS_ON
private:
#if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
void CheckHeldAndUnmark();
void CheckUnheldAndMark();
base::PlatformThreadRef owning_thread_ref_;
#endif // !NDEBUG || DCHECK_ALWAYS_ON
base::internal::LockImpl lock_;
MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex);
};
// MutexLocker -----------------------------------------------------------------
class MOJO_SCOPED_LOCKABLE MutexLocker {
public:
explicit MutexLocker(Mutex* mutex) MOJO_EXCLUSIVE_LOCK_FUNCTION(mutex)
: mutex_(mutex) {
this->mutex_->Lock();
}
~MutexLocker() MOJO_UNLOCK_FUNCTION() { this->mutex_->Unlock(); }
private:
Mutex* const mutex_;
MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLocker);
};
} // namespace system
} // namespace mojo
#endif // MOJO_EDK_SYSTEM_MUTEX_H_

View File

@ -1,250 +0,0 @@
// Copyright 2015 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/edk/system/mutex.h"
#include <stdlib.h>
#include "base/threading/platform_thread.h"
#include "mojo/edk/system/test_utils.h"
#include "mojo/public/cpp/system/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
namespace system {
namespace {
// Sleeps for a "very small" amount of time.
void EpsilonRandomSleep() {
test::Sleep(test::DeadlineFromMilliseconds(rand() % 20));
}
// Basic test to make sure that Lock()/Unlock()/TryLock() don't crash ----------
class BasicMutexTestThread : public base::PlatformThread::Delegate {
public:
explicit BasicMutexTestThread(Mutex* mutex) : mutex_(mutex), acquired_(0) {}
void ThreadMain() override {
for (int i = 0; i < 10; i++) {
mutex_->Lock();
mutex_->AssertHeld();
acquired_++;
mutex_->Unlock();
}
for (int i = 0; i < 10; i++) {
mutex_->Lock();
mutex_->AssertHeld();
acquired_++;
EpsilonRandomSleep();
mutex_->Unlock();
}
for (int i = 0; i < 10; i++) {
if (mutex_->TryLock()) {
mutex_->AssertHeld();
acquired_++;
EpsilonRandomSleep();
mutex_->Unlock();
}
}
}
int acquired() const { return acquired_; }
private:
Mutex* mutex_;
int acquired_;
MOJO_DISALLOW_COPY_AND_ASSIGN(BasicMutexTestThread);
};
TEST(MutexTest, Basic) {
Mutex mutex;
BasicMutexTestThread thread(&mutex);
base::PlatformThreadHandle handle;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
int acquired = 0;
for (int i = 0; i < 5; i++) {
mutex.Lock();
mutex.AssertHeld();
acquired++;
mutex.Unlock();
}
for (int i = 0; i < 10; i++) {
mutex.Lock();
mutex.AssertHeld();
acquired++;
EpsilonRandomSleep();
mutex.Unlock();
}
for (int i = 0; i < 10; i++) {
if (mutex.TryLock()) {
mutex.AssertHeld();
acquired++;
EpsilonRandomSleep();
mutex.Unlock();
}
}
for (int i = 0; i < 5; i++) {
mutex.Lock();
mutex.AssertHeld();
acquired++;
EpsilonRandomSleep();
mutex.Unlock();
}
base::PlatformThread::Join(handle);
EXPECT_GE(acquired, 20);
EXPECT_GE(thread.acquired(), 20);
}
// Test that TryLock() works as expected ---------------------------------------
class TryLockTestThread : public base::PlatformThread::Delegate {
public:
explicit TryLockTestThread(Mutex* mutex) : mutex_(mutex), got_lock_(false) {}
void ThreadMain() override MOJO_NO_THREAD_SAFETY_ANALYSIS {
got_lock_ = mutex_->TryLock();
if (got_lock_) {
mutex_->AssertHeld();
mutex_->Unlock();
}
}
bool got_lock() const { return got_lock_; }
private:
Mutex* mutex_;
bool got_lock_;
MOJO_DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
};
TEST(MutexTest, TryLock) MOJO_NO_THREAD_SAFETY_ANALYSIS {
Mutex mutex;
ASSERT_TRUE(mutex.TryLock());
// We now have the mutex....
// This thread will not be able to get the mutex.
{
TryLockTestThread thread(&mutex);
base::PlatformThreadHandle handle;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
base::PlatformThread::Join(handle);
ASSERT_FALSE(thread.got_lock());
}
mutex.Unlock();
// This thread will....
{
TryLockTestThread thread(&mutex);
base::PlatformThreadHandle handle;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
base::PlatformThread::Join(handle);
ASSERT_TRUE(thread.got_lock());
// But it released it....
ASSERT_TRUE(mutex.TryLock());
}
mutex.Unlock();
}
// Tests that mutexes actually exclude -----------------------------------------
class MutexLockTestThread : public base::PlatformThread::Delegate {
public:
MutexLockTestThread(Mutex* mutex, int* value)
: mutex_(mutex), value_(value) {}
// Static helper which can also be called from the main thread.
static void DoStuff(Mutex* mutex, int* value) {
for (int i = 0; i < 40; i++) {
mutex->Lock();
int v = *value;
EpsilonRandomSleep();
*value = v + 1;
mutex->Unlock();
}
}
void ThreadMain() override { DoStuff(mutex_, value_); }
private:
Mutex* mutex_;
int* value_;
MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
};
TEST(MutexTest, MutexTwoThreads) {
Mutex mutex;
int value = 0;
MutexLockTestThread thread(&mutex, &value);
base::PlatformThreadHandle handle;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread, &handle));
MutexLockTestThread::DoStuff(&mutex, &value);
base::PlatformThread::Join(handle);
EXPECT_EQ(2 * 40, value);
}
TEST(MutexTest, MutexFourThreads) {
Mutex mutex;
int value = 0;
MutexLockTestThread thread1(&mutex, &value);
MutexLockTestThread thread2(&mutex, &value);
MutexLockTestThread thread3(&mutex, &value);
base::PlatformThreadHandle handle1;
base::PlatformThreadHandle handle2;
base::PlatformThreadHandle handle3;
ASSERT_TRUE(base::PlatformThread::Create(0, &thread1, &handle1));
ASSERT_TRUE(base::PlatformThread::Create(0, &thread2, &handle2));
ASSERT_TRUE(base::PlatformThread::Create(0, &thread3, &handle3));
MutexLockTestThread::DoStuff(&mutex, &value);
base::PlatformThread::Join(handle1);
base::PlatformThread::Join(handle2);
base::PlatformThread::Join(handle3);
EXPECT_EQ(4 * 40, value);
}
// MutexLocker -----------------------------------------------------------------
TEST(MutexTest, MutexLocker) {
Mutex mutex;
{
MutexLocker locker(&mutex);
mutex.AssertHeld();
}
// The destruction of |locker| should unlock |mutex|.
ASSERT_TRUE(mutex.TryLock());
mutex.AssertHeld();
mutex.Unlock();
}
} // namespace
} // namespace system
} // namespace mojo

View File

@ -14,7 +14,6 @@
#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <type_traits>
#include "base/logging.h"
@ -38,15 +37,15 @@ class UserOptionsReader {
// Note: We initialize |options_reader_| without checking, since we do a check
// in |GetSizeForReader()|.
explicit UserOptionsReader(UserPointer<const Options> options)
: options_reader_(UserPointer<const char>::Reader::NoCheck(),
options.template ReinterpretCast<const char>(),
GetSizeForReader(options)) {}
: options_reader_(options, GetSizeForReader(options)) {}
bool is_valid() const { return !!options_reader_.GetPointer(); }
bool is_valid() const {
return options_reader_.GetPointer()->struct_size >= sizeof(uint32_t);
}
const Options& options() const {
DCHECK(is_valid());
return *reinterpret_cast<const Options*>(options_reader_.GetPointer());
return *options_reader_.GetPointer();
}
// Checks that the given (variable-size) |options| passed to the constructor
@ -64,20 +63,17 @@ class UserOptionsReader {
static inline size_t GetSizeForReader(UserPointer<const Options> options) {
uint32_t struct_size =
options.template ReinterpretCast<const uint32_t>().Get();
// Note: |PartialReader| will clear memory, so |is_valid()| will return
// false in this case.
if (struct_size < sizeof(uint32_t))
return 0;
// Check the full requested size.
// Note: Use |MOJO_ALIGNOF()| here to match the exact macro used in the
// declaration of Options structs.
internal::CheckUserPointerWithSize<MOJO_ALIGNOF(Options)>(options.pointer_,
struct_size);
options.template ReinterpretCast<const char>().CheckArray(struct_size);
// But we'll never look at more than |sizeof(Options)| bytes.
return std::min(static_cast<size_t>(struct_size), sizeof(Options));
// |PartialReader|'s constructor will automatically limit the amount copied
// to |sizeof(Options)|.
return struct_size;
}
UserPointer<const char>::Reader options_reader_;
typename UserPointer<const Options>::PartialReader options_reader_;
MOJO_DISALLOW_COPY_AND_ASSIGN(UserOptionsReader);
};

View File

@ -8,6 +8,9 @@
#include "base/logging.h"
using mojo::util::MutexLocker;
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -6,8 +6,9 @@
#define MOJO_EDK_SYSTEM_PLATFORM_HANDLE_DISPATCHER_H_
#include "mojo/edk/embedder/scoped_platform_handle.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/system/simple_dispatcher.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/edk/util/thread_annotations.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -17,7 +18,7 @@ namespace system {
// the embedder).
class PlatformHandleDispatcher final : public SimpleDispatcher {
public:
static RefPtr<PlatformHandleDispatcher> Create(
static util::RefPtr<PlatformHandleDispatcher> Create(
embedder::ScopedPlatformHandle platform_handle) {
return AdoptRef(new PlatformHandleDispatcher(platform_handle.Pass()));
}
@ -29,7 +30,7 @@ class PlatformHandleDispatcher final : public SimpleDispatcher {
// The "opposite" of |SerializeAndClose()|. (Typically this is called by
// |Dispatcher::Deserialize()|.)
static RefPtr<PlatformHandleDispatcher> Deserialize(
static util::RefPtr<PlatformHandleDispatcher> Deserialize(
Channel* channel,
const void* source,
size_t size,
@ -42,7 +43,8 @@ class PlatformHandleDispatcher final : public SimpleDispatcher {
// |Dispatcher| protected methods:
void CloseImplNoLock() override;
RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override;
util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
override;
void StartSerializeImplNoLock(Channel* channel,
size_t* max_size,
size_t* max_platform_handles) override

View File

@ -6,18 +6,21 @@
#include <stdio.h>
#include "base/memory/ref_counted.h"
#include "mojo/edk/test/scoped_test_dir.h"
#include <utility>
#include "mojo/edk/system/test/scoped_test_dir.h"
#include "mojo/edk/test/test_utils.h"
#include "mojo/edk/util/scoped_file.h"
#include "testing/gtest/include/gtest/gtest.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {
namespace {
TEST(PlatformHandleDispatcherTest, Basic) {
mojo::test::ScopedTestDir test_dir;
test::ScopedTestDir test_dir;
static const char kHelloWorld[] = "hello world";
@ -27,7 +30,7 @@ TEST(PlatformHandleDispatcherTest, Basic) {
fwrite(kHelloWorld, 1, sizeof(kHelloWorld), fp.get()));
embedder::ScopedPlatformHandle h(
mojo::test::PlatformHandleFromFILE(fp.Pass()));
mojo::test::PlatformHandleFromFILE(std::move(fp)));
EXPECT_FALSE(fp);
ASSERT_TRUE(h.is_valid());
@ -35,10 +38,10 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_FALSE(h.is_valid());
EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, dispatcher->GetType());
h = dispatcher->PassPlatformHandle().Pass();
h = dispatcher->PassPlatformHandle();
EXPECT_TRUE(h.is_valid());
fp = mojo::test::FILEFromPlatformHandle(h.Pass(), "rb").Pass();
fp = mojo::test::FILEFromPlatformHandle(h.Pass(), "rb");
EXPECT_FALSE(h.is_valid());
EXPECT_TRUE(fp);
@ -49,14 +52,14 @@ TEST(PlatformHandleDispatcherTest, Basic) {
EXPECT_STREQ(kHelloWorld, read_buffer);
// Try getting the handle again. (It should fail cleanly.)
h = dispatcher->PassPlatformHandle().Pass();
h = dispatcher->PassPlatformHandle();
EXPECT_FALSE(h.is_valid());
EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
}
TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) {
mojo::test::ScopedTestDir test_dir;
test::ScopedTestDir test_dir;
static const char kFooBar[] = "foo bar";
@ -64,7 +67,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) {
EXPECT_EQ(sizeof(kFooBar), fwrite(kFooBar, 1, sizeof(kFooBar), fp.get()));
auto dispatcher = PlatformHandleDispatcher::Create(
mojo::test::PlatformHandleFromFILE(fp.Pass()));
mojo::test::PlatformHandleFromFILE(std::move(fp)));
DispatcherTransport transport(
test::DispatcherTryStartTransport(dispatcher.get()));
@ -76,7 +79,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) {
ASSERT_TRUE(generic_dispatcher);
transport.End();
dispatcher->AssertHasOneRef();
EXPECT_TRUE(dispatcher->HasOneRef());
dispatcher = nullptr;
ASSERT_EQ(Dispatcher::Type::PLATFORM_HANDLE, generic_dispatcher->GetType());
@ -84,7 +87,7 @@ TEST(PlatformHandleDispatcherTest, CreateEquivalentDispatcherAndClose) {
static_cast<PlatformHandleDispatcher*>(generic_dispatcher.get()));
fp = mojo::test::FILEFromPlatformHandle(dispatcher->PassPlatformHandle(),
"rb").Pass();
"rb");
EXPECT_TRUE(fp);
rewind(fp.get());

View File

@ -13,6 +13,8 @@
#include "mojo/edk/system/local_message_pipe_endpoint.h"
#include "mojo/edk/system/message_pipe_dispatcher.h"
using mojo::util::RefPtr;
namespace mojo {
namespace system {

View File

@ -7,7 +7,7 @@
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/message_pipe_endpoint.h"
#include "mojo/edk/system/ref_ptr.h"
#include "mojo/edk/util/ref_ptr.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
@ -28,7 +28,8 @@ class MessagePipe;
// a |MessagePipeDispatcher|.
class ProxyMessagePipeEndpoint final : public MessagePipeEndpoint {
public:
explicit ProxyMessagePipeEndpoint(RefPtr<ChannelEndpoint>&& channel_endpoint);
explicit ProxyMessagePipeEndpoint(
util::RefPtr<ChannelEndpoint>&& channel_endpoint);
~ProxyMessagePipeEndpoint() override;
// Returns |channel_endpoint_| and resets |channel_endpoint_| to null. This
@ -37,7 +38,7 @@ class ProxyMessagePipeEndpoint final : public MessagePipeEndpoint {
// Note: The returned |ChannelEndpoint| must have its client changed while
// still under |MessagePipe|'s lock (which this must have also been called
// under).
RefPtr<ChannelEndpoint> ReleaseChannelEndpoint();
util::RefPtr<ChannelEndpoint> ReleaseChannelEndpoint();
// |MessagePipeEndpoint| implementation:
Type GetType() const override;
@ -48,7 +49,7 @@ class ProxyMessagePipeEndpoint final : public MessagePipeEndpoint {
private:
void DetachIfNecessary();
RefPtr<ChannelEndpoint> channel_endpoint_;
util::RefPtr<ChannelEndpoint> channel_endpoint_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyMessagePipeEndpoint);
};

View File

@ -16,6 +16,8 @@
#include "mojo/edk/system/message_in_transit.h"
#include "mojo/edk/system/transport_data.h"
using mojo::util::MutexLocker;
namespace mojo {
namespace system {

Some files were not shown because too many files have changed in this diff Show More