Commit 053dc146 authored by yzshen's avatar yzshen Committed by Commit bot

Mojo C++ bindings: remove the lock in MultiplexRouter if it only serves a single interface.

BUG=594244

Review-Url: https://codereview.chromium.org/2345013002
Cr-Commit-Position: refs/heads/master@{#419036}
parent 90625243
......@@ -55,6 +55,7 @@ static_library("bindings") {
"lib/interface_ptr_state.h",
"lib/map_data_internal.h",
"lib/map_serialization.h",
"lib/may_auto_lock.h",
"lib/message.cc",
"lib/message_buffer.cc",
"lib/message_buffer.h",
......
......@@ -231,8 +231,9 @@ template <typename Interface>
void GetDummyProxyForTesting(AssociatedInterfacePtr<Interface>* proxy) {
MessagePipe pipe;
scoped_refptr<internal::MultiplexRouter> router =
new internal::MultiplexRouter(false, std::move(pipe.handle0),
base::ThreadTaskRunnerHandle::Get());
new internal::MultiplexRouter(std::move(pipe.handle0),
internal::MultiplexRouter::MULTI_INTERFACE,
false, base::ThreadTaskRunnerHandle::Get());
std::unique_ptr<AssociatedGroup> group = router->CreateAssociatedGroup();
GetProxy(proxy, group.get());
}
......
......@@ -146,7 +146,8 @@ void MultiplexedBindingState::BindInternal(
uint32_t interface_version) {
DCHECK(!router_);
router_ = new internal::MultiplexRouter(false, std::move(handle), runner);
router_ = new MultiplexRouter(
std::move(handle), MultiplexRouter::MULTI_INTERFACE, false, runner);
router_->SetMasterInterfaceName(interface_name);
endpoint_client_.reset(new InterfaceEndpointClient(
......
......@@ -12,37 +12,11 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
namespace mojo {
namespace {
// Similar to base::AutoLock, except that it does nothing if |lock| passed into
// the constructor is null.
class MayAutoLock {
public:
explicit MayAutoLock(base::Lock* lock) : lock_(lock) {
if (lock_)
lock_->Acquire();
}
~MayAutoLock() {
if (lock_) {
lock_->AssertAcquired();
lock_->Release();
}
}
private:
base::Lock* lock_;
DISALLOW_COPY_AND_ASSIGN(MayAutoLock);
};
} // namespace
// ----------------------------------------------------------------------------
Connector::Connector(ScopedMessagePipeHandle message_pipe,
ConnectorConfig config,
scoped_refptr<base::SingleThreadTaskRunner> runner)
......@@ -73,7 +47,7 @@ void Connector::CloseMessagePipe() {
DCHECK(thread_checker_.CalledOnValidThread());
CancelWait();
MayAutoLock locker(lock_.get());
internal::MayAutoLock locker(lock_.get());
message_pipe_.reset();
base::AutoLock lock(connected_lock_);
......@@ -84,7 +58,7 @@ ScopedMessagePipeHandle Connector::PassMessagePipe() {
DCHECK(thread_checker_.CalledOnValidThread());
CancelWait();
MayAutoLock locker(lock_.get());
internal::MayAutoLock locker(lock_.get());
ScopedMessagePipeHandle message_pipe = std::move(message_pipe_);
base::AutoLock lock(connected_lock_);
......@@ -149,7 +123,7 @@ bool Connector::Accept(Message* message) {
if (error_)
return false;
MayAutoLock locker(lock_.get());
internal::MayAutoLock locker(lock_.get());
if (!message_pipe_.is_valid() || drop_writes_)
return true;
......@@ -331,7 +305,7 @@ void Connector::HandleError(bool force_pipe_reset, bool force_async_handler) {
if (force_pipe_reset) {
CancelWait();
MayAutoLock locker(lock_.get());
internal::MayAutoLock locker(lock_.get());
message_pipe_.reset();
MessagePipe dummy_pipe;
message_pipe_ = std::move(dummy_pipe.handle0);
......
......@@ -345,7 +345,8 @@ class InterfacePtrState<Interface, true> {
if (!handle_.is_valid())
return;
router_ = new MultiplexRouter(true, std::move(handle_), runner_);
router_ = new MultiplexRouter(
std::move(handle_), MultiplexRouter::MULTI_INTERFACE, true, runner_);
router_->SetMasterInterfaceName(Interface::Name_);
endpoint_client_.reset(new InterfaceEndpointClient(
router_->CreateLocalEndpointHandle(kMasterInterfaceId), nullptr,
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/macros.h"
#include "base/synchronization/lock.h"
namespace mojo {
namespace internal {
// Similar to base::AutoLock, except that it does nothing if |lock| passed into
// the constructor is null.
class MayAutoLock {
public:
explicit MayAutoLock(base::Lock* lock) : lock_(lock) {
if (lock_)
lock_->Acquire();
}
~MayAutoLock() {
if (lock_) {
lock_->AssertAcquired();
lock_->Release();
}
}
private:
base::Lock* lock_;
DISALLOW_COPY_AND_ASSIGN(MayAutoLock);
};
// Similar to base::AutoUnlock, except that it does nothing if |lock| passed
// into the constructor is null.
class MayAutoUnlock {
public:
explicit MayAutoUnlock(base::Lock* lock) : lock_(lock) {
if (lock_) {
lock_->AssertAcquired();
lock_->Release();
}
}
~MayAutoUnlock() {
if (lock_)
lock_->Acquire();
}
private:
base::Lock* lock_;
DISALLOW_COPY_AND_ASSIGN(MayAutoUnlock);
};
} // namespace internal
} // namespace mojo
......@@ -18,6 +18,7 @@
#include "mojo/public/cpp/bindings/associated_group.h"
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
namespace mojo {
......@@ -50,13 +51,13 @@ class MultiplexRouter::InterfaceEndpoint
bool closed() const { return closed_; }
void set_closed() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
closed_ = true;
}
bool peer_closed() const { return peer_closed_; }
void set_peer_closed() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
peer_closed_ = true;
}
......@@ -68,7 +69,7 @@ class MultiplexRouter::InterfaceEndpoint
void AttachClient(InterfaceEndpointClient* client,
scoped_refptr<base::SingleThreadTaskRunner> runner) {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
DCHECK(!client_);
DCHECK(!closed_);
DCHECK(runner->BelongsToCurrentThread());
......@@ -80,7 +81,7 @@ class MultiplexRouter::InterfaceEndpoint
// This method must be called on the same thread as the corresponding
// AttachClient() call.
void DetachClient() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
DCHECK(client_);
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(!closed_);
......@@ -91,7 +92,7 @@ class MultiplexRouter::InterfaceEndpoint
}
void SignalSyncMessageEvent() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
if (event_signalled_)
return;
......@@ -104,7 +105,7 @@ class MultiplexRouter::InterfaceEndpoint
}
void ResetSyncMessageSignal() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
if (!event_signalled_)
return;
......@@ -146,7 +147,7 @@ class MultiplexRouter::InterfaceEndpoint
friend class base::RefCounted<InterfaceEndpoint>;
~InterfaceEndpoint() override {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
DCHECK(!client_);
DCHECK(closed_);
......@@ -164,7 +165,7 @@ class MultiplexRouter::InterfaceEndpoint
DCHECK_EQ(MOJO_RESULT_OK, result);
bool reset_sync_watcher = false;
{
base::AutoLock locker(router_->lock_);
MayAutoLock locker(router_->lock_.get());
bool more_to_process = router_->ProcessFirstSyncMessageForEndpoint(id_);
......@@ -189,7 +190,7 @@ class MultiplexRouter::InterfaceEndpoint
return;
{
base::AutoLock locker(router_->lock_);
MayAutoLock locker(router_->lock_.get());
EnsureEventMessagePipeExists();
auto iter = router_->sync_message_tasks_.find(id_);
......@@ -203,7 +204,7 @@ class MultiplexRouter::InterfaceEndpoint
}
void EnsureEventMessagePipeExists() {
router_->lock_.AssertAcquired();
router_->AssertLockAcquired();
if (sync_message_event_receiver_.is_valid())
return;
......@@ -281,16 +282,19 @@ struct MultiplexRouter::Task {
};
MultiplexRouter::MultiplexRouter(
bool set_interface_id_namesapce_bit,
ScopedMessagePipeHandle message_pipe,
Config config,
bool set_interface_id_namesapce_bit,
scoped_refptr<base::SingleThreadTaskRunner> runner)
: set_interface_id_namespace_bit_(set_interface_id_namesapce_bit),
task_runner_(runner),
header_validator_(nullptr),
filters_(this),
connector_(std::move(message_pipe),
Connector::MULTI_THREADED_SEND,
config == SINGLE_INTERFACE ? Connector::SINGLE_THREADED_SEND
: Connector::MULTI_THREADED_SEND,
std::move(runner)),
lock_(config == SINGLE_INTERFACE ? nullptr : new base::Lock),
control_message_handler_(this),
control_message_proxy_(&connector_),
next_interface_id_value_(1),
......@@ -315,7 +319,7 @@ MultiplexRouter::MultiplexRouter(
}
MultiplexRouter::~MultiplexRouter() {
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
sync_message_tasks_.clear();
tasks_.clear();
......@@ -343,7 +347,7 @@ void MultiplexRouter::SetMasterInterfaceName(const std::string& name) {
void MultiplexRouter::CreateEndpointHandlePair(
ScopedInterfaceEndpointHandle* local_endpoint,
ScopedInterfaceEndpointHandle* remote_endpoint) {
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
uint32_t id = 0;
do {
if (next_interface_id_value_ >= kInterfaceIdNamespaceMask)
......@@ -367,7 +371,7 @@ ScopedInterfaceEndpointHandle MultiplexRouter::CreateLocalEndpointHandle(
if (!IsValidInterfaceId(id))
return ScopedInterfaceEndpointHandle();
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
bool inserted = false;
InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted);
if (inserted) {
......@@ -386,7 +390,7 @@ void MultiplexRouter::CloseEndpointHandle(InterfaceId id, bool is_local) {
if (!IsValidInterfaceId(id))
return;
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
if (!is_local) {
DCHECK(base::ContainsKey(endpoints_, id));
......@@ -419,7 +423,7 @@ InterfaceEndpointController* MultiplexRouter::AttachEndpointClient(
DCHECK(IsValidInterfaceId(id));
DCHECK(client);
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
DCHECK(base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = endpoints_[id].get();
......@@ -438,7 +442,7 @@ void MultiplexRouter::DetachEndpointClient(
DCHECK(IsValidInterfaceId(id));
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
DCHECK(base::ContainsKey(endpoints_, id));
InterfaceEndpoint* endpoint = endpoints_[id].get();
......@@ -467,7 +471,7 @@ void MultiplexRouter::PauseIncomingMethodCallProcessing() {
DCHECK(thread_checker_.CalledOnValidThread());
connector_.PauseIncomingMethodCallProcessing();
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
paused_ = true;
for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter)
......@@ -478,7 +482,7 @@ void MultiplexRouter::ResumeIncomingMethodCallProcessing() {
DCHECK(thread_checker_.CalledOnValidThread());
connector_.ResumeIncomingMethodCallProcessing();
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
paused_ = false;
for (auto iter = endpoints_.begin(); iter != endpoints_.end(); ++iter) {
......@@ -492,7 +496,7 @@ void MultiplexRouter::ResumeIncomingMethodCallProcessing() {
bool MultiplexRouter::HasAssociatedEndpoints() const {
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
if (endpoints_.size() > 1)
return true;
......@@ -504,7 +508,7 @@ bool MultiplexRouter::HasAssociatedEndpoints() const {
void MultiplexRouter::EnableTestingMode() {
DCHECK(thread_checker_.CalledOnValidThread());
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
testing_mode_ = true;
connector_.set_enforce_errors_from_incoming_receiver(false);
......@@ -514,7 +518,7 @@ bool MultiplexRouter::Accept(Message* message) {
DCHECK(thread_checker_.CalledOnValidThread());
scoped_refptr<MultiplexRouter> protector(this);
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
DCHECK(!paused_);
......@@ -553,7 +557,7 @@ bool MultiplexRouter::Accept(Message* message) {
}
bool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) {
lock_.AssertAcquired();
AssertLockAcquired();
if (IsMasterInterfaceId(id))
return false;
......@@ -578,7 +582,7 @@ bool MultiplexRouter::OnPeerAssociatedEndpointClosed(InterfaceId id) {
}
bool MultiplexRouter::OnAssociatedEndpointClosedBeforeSent(InterfaceId id) {
lock_.AssertAcquired();
AssertLockAcquired();
if (IsMasterInterfaceId(id))
return false;
......@@ -596,7 +600,7 @@ void MultiplexRouter::OnPipeConnectionError() {
DCHECK(thread_checker_.CalledOnValidThread());
scoped_refptr<MultiplexRouter> protector(this);
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
encountered_error_ = true;
......@@ -621,7 +625,7 @@ void MultiplexRouter::OnPipeConnectionError() {
void MultiplexRouter::ProcessTasks(
ClientCallBehavior client_call_behavior,
base::SingleThreadTaskRunner* current_task_runner) {
lock_.AssertAcquired();
AssertLockAcquired();
if (posted_to_process_tasks_)
return;
......@@ -665,7 +669,7 @@ void MultiplexRouter::ProcessTasks(
}
bool MultiplexRouter::ProcessFirstSyncMessageForEndpoint(InterfaceId id) {
lock_.AssertAcquired();
AssertLockAcquired();
auto iter = sync_message_tasks_.find(id);
if (iter == sync_message_tasks_.end())
......@@ -704,7 +708,7 @@ bool MultiplexRouter::ProcessNotifyErrorTask(
DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
DCHECK(!paused_);
lock_.AssertAcquired();
AssertLockAcquired();
InterfaceEndpoint* endpoint = task->endpoint_to_notify.get();
if (!endpoint->client())
return true;
......@@ -724,7 +728,7 @@ bool MultiplexRouter::ProcessNotifyErrorTask(
//
// It is safe to call into |client| without the lock. Because |client| is
// always accessed on the same thread, including DetachEndpointClient().
base::AutoUnlock unlocker(lock_);
MayAutoUnlock unlocker(lock_.get());
client->NotifyError();
}
return true;
......@@ -737,7 +741,7 @@ bool MultiplexRouter::ProcessIncomingMessage(
DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread());
DCHECK(!paused_);
DCHECK(message);
lock_.AssertAcquired();
AssertLockAcquired();
if (message->IsNull()) {
// This is a sync message and has been processed during sync handle
......@@ -811,7 +815,7 @@ bool MultiplexRouter::ProcessIncomingMessage(
//
// It is safe to call into |client| without the lock. Because |client| is
// always accessed on the same thread, including DetachEndpointClient().
base::AutoUnlock unlocker(lock_);
MayAutoUnlock unlocker(lock_.get());
result = client->HandleIncomingMessage(message);
}
if (!result)
......@@ -822,7 +826,7 @@ bool MultiplexRouter::ProcessIncomingMessage(
void MultiplexRouter::MaybePostToProcessTasks(
base::SingleThreadTaskRunner* task_runner) {
lock_.AssertAcquired();
AssertLockAcquired();
if (posted_to_process_tasks_)
return;
......@@ -835,7 +839,7 @@ void MultiplexRouter::MaybePostToProcessTasks(
void MultiplexRouter::LockAndCallProcessTasks() {
// There is no need to hold a ref to this class in this case because this is
// always called using base::Bind(), which holds a ref.
base::AutoLock locker(lock_);
MayAutoLock locker(lock_.get());
posted_to_process_tasks_ = false;
scoped_refptr<base::SingleThreadTaskRunner> runner(
std::move(posted_to_task_runner_));
......@@ -861,7 +865,7 @@ void MultiplexRouter::UpdateEndpointStateMayRemove(
}
void MultiplexRouter::RaiseErrorInNonTestingMode() {
lock_.AssertAcquired();
AssertLockAcquired();
if (!testing_mode_)
RaiseError();
}
......@@ -869,7 +873,7 @@ void MultiplexRouter::RaiseErrorInNonTestingMode() {
MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint(
InterfaceId id,
bool* inserted) {
lock_.AssertAcquired();
AssertLockAcquired();
// Either |inserted| is nullptr or it points to a boolean initialized as
// false.
DCHECK(!inserted || !*inserted);
......@@ -888,5 +892,12 @@ MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint(
return endpoint;
}
void MultiplexRouter::AssertLockAcquired() {
#if DCHECK_IS_ON()
if (lock_)
lock_->AssertAcquired();
#endif
}
} // namespace internal
} // namespace mojo
......@@ -56,10 +56,22 @@ class MultiplexRouter
public AssociatedGroupController,
public PipeControlMessageHandlerDelegate {
public:
enum Config {
// There is only the master interface running on this router. Please note
// that because of interface versioning, the other side of the message pipe
// may use a newer master interface definition which passes associated
// interfaces. In that case, this router may still receive pipe control
// messages or messages targetting associated interfaces.
SINGLE_INTERFACE,
// There may be associated interfaces running on this router.
MULTI_INTERFACE
};
// If |set_interface_id_namespace_bit| is true, the interface IDs generated by
// this router will have the highest bit set.
MultiplexRouter(bool set_interface_id_namespace_bit,
ScopedMessagePipeHandle message_pipe,
MultiplexRouter(ScopedMessagePipeHandle message_pipe,
Config config,
bool set_interface_id_namespace_bit,
scoped_refptr<base::SingleThreadTaskRunner> runner);
// Sets the master interface name for this router. Only used when reporting
......@@ -205,6 +217,8 @@ class MultiplexRouter
InterfaceEndpoint* FindOrInsertEndpoint(InterfaceId id, bool* inserted);
void AssertLockAcquired();
// Whether to set the namespace bit when generating interface IDs. Please see
// comments of kInterfaceIdNamespaceMask.
const bool set_interface_id_namespace_bit_;
......@@ -220,7 +234,8 @@ class MultiplexRouter
base::ThreadChecker thread_checker_;
// Protects the following members.
mutable base::Lock lock_;
// Sets to nullptr in Config::SINGLE_INTERFACE mode.
std::unique_ptr<base::Lock> lock_;
PipeControlMessageHandler control_message_handler_;
PipeControlMessageProxy control_message_proxy_;
......
......@@ -113,9 +113,11 @@ class AssociatedInterfaceTest : public testing::Test {
void CreateRouterPair(scoped_refptr<MultiplexRouter>* router0,
scoped_refptr<MultiplexRouter>* router1) {
MessagePipe pipe;
*router0 = new MultiplexRouter(true, std::move(pipe.handle0),
*router0 = new MultiplexRouter(std::move(pipe.handle0),
MultiplexRouter::MULTI_INTERFACE, true,
base::ThreadTaskRunnerHandle::Get());
*router1 = new MultiplexRouter(false, std::move(pipe.handle1),
*router1 = new MultiplexRouter(std::move(pipe.handle1),
MultiplexRouter::MULTI_INTERFACE, false,
base::ThreadTaskRunnerHandle::Get());
}
......
......@@ -217,11 +217,13 @@ TEST_F(MojoBindingsPerftest, RouterPingPong) {
TEST_F(MojoBindingsPerftest, MultiplexRouterPingPong) {
MessagePipe pipe;
scoped_refptr<internal::MultiplexRouter> router0(
new internal::MultiplexRouter(true, std::move(pipe.handle0),
base::ThreadTaskRunnerHandle::Get()));
new internal::MultiplexRouter(std::move(pipe.handle0),
internal::MultiplexRouter::SINGLE_INTERFACE,
true, base::ThreadTaskRunnerHandle::Get()));
scoped_refptr<internal::MultiplexRouter> router1(
new internal::MultiplexRouter(false, std::move(pipe.handle1),
base::ThreadTaskRunnerHandle::Get()));
new internal::MultiplexRouter(
std::move(pipe.handle1), internal::MultiplexRouter::SINGLE_INTERFACE,
false, base::ThreadTaskRunnerHandle::Get()));
PingPongPaddle paddle0(nullptr);
PingPongPaddle paddle1(nullptr);
......@@ -302,7 +304,8 @@ TEST_F(MojoBindingsPerftest, RouterDispatchCost) {
TEST_F(MojoBindingsPerftest, MultiplexRouterDispatchCost) {
MessagePipe pipe;
scoped_refptr<internal::MultiplexRouter> router(new internal::MultiplexRouter(
true, std::move(pipe.handle0), base::ThreadTaskRunnerHandle::Get()));
std::move(pipe.handle0), internal::MultiplexRouter::SINGLE_INTERFACE,
true, base::ThreadTaskRunnerHandle::Get()));
CounterReceiver receiver;
InterfaceEndpointClient client(
router->CreateLocalEndpointHandle(kMasterInterfaceId), &receiver, nullptr,
......
......@@ -31,9 +31,11 @@ class MultiplexRouterTest : public testing::Test {
void SetUp() override {
MessagePipe pipe;
router0_ = new MultiplexRouter(true, std::move(pipe.handle0),
router0_ = new MultiplexRouter(std::move(pipe.handle0),
MultiplexRouter::MULTI_INTERFACE, false,
base::ThreadTaskRunnerHandle::Get());
router1_ = new MultiplexRouter(true, std::move(pipe.handle1),
router1_ = new MultiplexRouter(std::move(pipe.handle1),
MultiplexRouter::MULTI_INTERFACE, true,
base::ThreadTaskRunnerHandle::Get());
router0_->CreateEndpointHandlePair(&endpoint0_, &endpoint1_);
endpoint1_ =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment