blob: fc3f48f981dbae63c5d577e3c910f88d19c3313d [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "mojo/public/cpp/bindings/connection_group.h"
#include "base/bind.h"
namespace mojo {
ConnectionGroup::Ref::Ref() = default;
ConnectionGroup::Ref::Ref(const Ref& other) {
*this = other;
}
ConnectionGroup::Ref::Ref(Ref&& other) noexcept {
*this = std::move(other);
}
ConnectionGroup::Ref::~Ref() {
reset();
}
ConnectionGroup::Ref& ConnectionGroup::Ref::operator=(const Ref& other) {
reset();
type_ = Type::kStrong;
group_ = other.group_;
group_->AddGroupRef();
return *this;
}
ConnectionGroup::Ref& ConnectionGroup::Ref::operator=(Ref&& other) noexcept {
reset();
type_ = other.type_;
group_.swap(other.group_);
return *this;
}
void ConnectionGroup::Ref::reset() {
if (type_ == Type::kStrong && group_)
group_->ReleaseGroupRef();
type_ = Type::kWeak;
group_.reset();
}
ConnectionGroup::Ref ConnectionGroup::Ref::WeakCopy() const {
DCHECK(group_->notification_task_runner_->RunsTasksInCurrentSequence());
return Ref(group_);
}
bool ConnectionGroup::Ref::HasZeroRefs() const {
DCHECK(group_->notification_task_runner_->RunsTasksInCurrentSequence());
return group_->num_refs_ == 0;
}
void ConnectionGroup::Ref::SetParentGroup(Ref parent_group) {
group_->notification_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&ConnectionGroup::SetParentGroup, group_,
std::move(parent_group)));
}
ConnectionGroup::Ref::Ref(scoped_refptr<ConnectionGroup> group)
: group_(std::move(group)) {}
// static
ConnectionGroup::Ref ConnectionGroup::Create(
base::RepeatingClosure callback,
scoped_refptr<base::SequencedTaskRunner> task_runner) {
return Ref(base::WrapRefCounted(
new ConnectionGroup(std::move(callback), std::move(task_runner))));
}
ConnectionGroup::ConnectionGroup(
base::RepeatingClosure callback,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: notification_callback_(std::move(callback)),
notification_task_runner_(std::move(task_runner)) {}
ConnectionGroup::~ConnectionGroup() {
// Just a sanity check. This ref-count should always be adjusted before the
// internal RefCountedThreadSafe ref-count, so we should never hit the
// destructor with a non-zero |num_refs_|.
DCHECK_EQ(num_refs_, 0u);
}
void ConnectionGroup::AddGroupRef() {
++num_refs_;
}
void ConnectionGroup::ReleaseGroupRef() {
DCHECK_GT(num_refs_, 0u);
--num_refs_;
if (num_refs_ == 0 && notification_task_runner_) {
notification_task_runner_->PostTask(FROM_HERE,
base::BindOnce(notification_callback_));
}
}
void ConnectionGroup::SetParentGroup(Ref parent_group) {
DCHECK(notification_task_runner_->RunsTasksInCurrentSequence());
DCHECK(!parent_group_);
parent_group_ = std::move(parent_group);
}
} // namespace mojo