Commit 477ab86d authored by Kyle Qian's avatar Kyle Qian Committed by Commit Bot

Implement AtomicBoolean and AtomicReference for CrOS Nearby.

This CL includes concrete implementations for the abstract classes
AtomicBoolean and AtomicReference defined in the Nearby library. An
AtomicBoolean is a boolean value that may be updated atomically, and an
AtomicReference is an object reference that may be updated atomically.

Because the actual Nearby library has yet to be merged into the CrOS
directory, this CL includes stand-in Nearby abstract classes under
the temporary directory //chromeos/components/nearby/library.
This directory will be removed after the Nearby library gets imported
to //third_party (in-progress CL:
https://chromium-review.googlesource.com/c/chromium/src/+/1113198).

Bug: 861813
Change-Id: Ibbda1bd35e3fb63eed0ae492ecebb3d61fa43050
Reviewed-on: https://chromium-review.googlesource.com/1142478
Commit-Queue: Kyle Qian <kyleqian@google.com>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584564}
parent 45cf5409
......@@ -6,6 +6,9 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
static_library("nearby") {
sources = [
"atomic_boolean_impl.cc",
"atomic_boolean_impl.h",
"atomic_reference_impl.h",
"count_down_latch_impl.cc",
"count_down_latch_impl.h",
"hash_utils_impl.cc",
......@@ -28,6 +31,8 @@ source_set("unit_tests") {
testonly = true
sources = [
"atomic_boolean_impl_unittests.cc",
"atomic_reference_impl_unittests.cc",
"count_down_latch_impl_unittests.cc",
"hash_utils_impl_unittests.cc",
"settable_future_impl_unittests.cc",
......
// Copyright (c) 2018 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 "chromeos/components/nearby/atomic_boolean_impl.h"
namespace {
base::subtle::AtomicWord BoolToAtomicWord(bool value) {
return value ? 1 : 0;
}
bool AtomicWordToBool(base::subtle::AtomicWord value) {
return value == 0 ? false : true;
}
} // namespace
namespace chromeos {
namespace nearby {
AtomicBooleanImpl::AtomicBooleanImpl() = default;
AtomicBooleanImpl::~AtomicBooleanImpl() = default;
bool AtomicBooleanImpl::get() {
return AtomicWordToBool(base::subtle::Acquire_Load(&boolean_));
}
void AtomicBooleanImpl::set(bool value) {
base::subtle::Release_Store(&boolean_, BoolToAtomicWord(value));
}
} // namespace nearby
} // namespace chromeos
// Copyright (c) 2018 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 CHROMEOS_COMPONENTS_NEARBY_ATOMIC_BOOLEAN_IMPL_H_
#define CHROMEOS_COMPONENTS_NEARBY_ATOMIC_BOOLEAN_IMPL_H_
#include "base/atomicops.h"
#include "base/macros.h"
#include "chromeos/components/nearby/library/atomic_boolean.h"
namespace chromeos {
namespace nearby {
// Concrete location::nearby::AtomicBoolean implementation.
class AtomicBooleanImpl : public location::nearby::AtomicBoolean {
public:
AtomicBooleanImpl();
~AtomicBooleanImpl() override;
private:
// location::nearby::AtomicBoolean:
bool get() override;
void set(bool value) override;
base::subtle::AtomicWord boolean_ = 0;
DISALLOW_COPY_AND_ASSIGN(AtomicBooleanImpl);
};
} // namespace nearby
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_NEARBY_ATOMIC_BOOLEAN_IMPL_H_
// Copyright (c) 2018 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 "chromeos/components/nearby/atomic_boolean_impl.h"
#include "base/macros.h"
#include "base/task/post_task.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "chromeos/components/nearby/library/atomic_boolean.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace nearby {
class AtomicBooleanImplTest : public testing::Test {
protected:
AtomicBooleanImplTest()
: atomic_boolean_(std::make_unique<AtomicBooleanImpl>()) {}
void SetAtomicBooleanOnThread(const base::Thread& thread, bool value) {
thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&AtomicBooleanImplTest::SetAtomicBoolean,
base::Unretained(this), value));
}
void VerifyAtomicBooleanOnThread(const base::Thread& thread, bool value) {
thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&AtomicBooleanImplTest::VerifyAtomicBoolean,
base::Unretained(this), value));
}
void VerifyAtomicBoolean(bool value) { EXPECT_EQ(value, GetAtomicBoolean()); }
void SetAtomicBoolean(bool value) { atomic_boolean_->set(value); }
bool GetAtomicBoolean() { return atomic_boolean_->get(); }
void TinyTimeout() {
// As of writing, tiny_timeout() is 100ms.
base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
}
private:
std::unique_ptr<location::nearby::AtomicBoolean> atomic_boolean_;
DISALLOW_COPY_AND_ASSIGN(AtomicBooleanImplTest);
};
TEST_F(AtomicBooleanImplTest, SetGetOnSameThread) {
VerifyAtomicBoolean(false);
SetAtomicBoolean(true);
VerifyAtomicBoolean(true);
}
TEST_F(AtomicBooleanImplTest, MultipleSetGetOnSameThread) {
VerifyAtomicBoolean(false);
SetAtomicBoolean(true);
VerifyAtomicBoolean(true);
SetAtomicBoolean(true);
VerifyAtomicBoolean(true);
SetAtomicBoolean(false);
VerifyAtomicBoolean(false);
SetAtomicBoolean(true);
VerifyAtomicBoolean(true);
}
TEST_F(AtomicBooleanImplTest, SetOnNewThread) {
VerifyAtomicBoolean(false);
base::Thread thread("AtomicBooleanImplTest.SetOnNewThread");
EXPECT_TRUE(thread.Start());
SetAtomicBooleanOnThread(thread, true);
TinyTimeout();
VerifyAtomicBoolean(true);
}
TEST_F(AtomicBooleanImplTest, GetOnNewThread) {
VerifyAtomicBoolean(false);
SetAtomicBoolean(true);
EXPECT_TRUE(GetAtomicBoolean());
base::Thread thread("AtomicBooleanImplTest.GetOnNewThread");
EXPECT_TRUE(thread.Start());
VerifyAtomicBooleanOnThread(thread, true);
}
} // namespace nearby
} // namespace chromeos
// Copyright (c) 2018 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 CHROMEOS_COMPONENTS_NEARBY_ATOMIC_REFERENCE_IMPL_H_
#define CHROMEOS_COMPONENTS_NEARBY_ATOMIC_REFERENCE_IMPL_H_
#include <utility>
#include "base/macros.h"
#include "base/synchronization/lock.h"
#include "chromeos/components/nearby/library/atomic_reference.h"
namespace chromeos {
namespace nearby {
// Concrete location::nearby::AtomicReference implementation.
template <typename T>
class AtomicReferenceImpl : public location::nearby::AtomicReference<T> {
public:
explicit AtomicReferenceImpl(T initial_value) : value_(initial_value) {}
~AtomicReferenceImpl() override = default;
private:
// location::nearby::AtomicReference:
T get() override {
base::AutoLock al(value_lock_);
return value_;
}
// location::nearby::AtomicReference:
void set(T value) override {
base::AutoLock al(value_lock_);
value_ = value;
}
T value_;
base::Lock value_lock_;
DISALLOW_COPY_AND_ASSIGN(AtomicReferenceImpl);
};
} // namespace nearby
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_NEARBY_ATOMIC_REFERENCE_IMPL_H__
// Copyright (c) 2018 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 "chromeos/components/nearby/atomic_reference_impl.h"
#include "base/macros.h"
#include "base/task/post_task.h"
#include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h"
#include "base/threading/thread.h"
#include "base/unguessable_token.h"
#include "chromeos/components/nearby/library/atomic_reference.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace nearby {
template <typename T>
class GenericAtomicReferenceImplTest : public testing::Test {
protected:
GenericAtomicReferenceImplTest() = default;
void SetValueInThread(const base::Thread& thread, T value) {
thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&GenericAtomicReferenceImplTest::SetValue,
base::Unretained(this), value));
}
void VerifyValueInThread(const base::Thread& thread, T value) {
thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&GenericAtomicReferenceImplTest::VerifyValue,
base::Unretained(this), value));
}
void VerifyValue(T value) { EXPECT_EQ(value, GetValue()); }
void SetValue(T value) { atomic_reference_->set(value); }
T GetValue() { return atomic_reference_->get(); }
void TinyTimeout() {
// As of writing, tiny_timeout() is 100ms.
base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
}
std::unique_ptr<location::nearby::AtomicReference<T>> atomic_reference_;
private:
DISALLOW_COPY_AND_ASSIGN(GenericAtomicReferenceImplTest);
};
class UnguessableTokenAtomicReferenceImplTest
: public GenericAtomicReferenceImplTest<base::UnguessableToken> {
protected:
UnguessableTokenAtomicReferenceImplTest()
: initial_value_(base::UnguessableToken::Create()) {}
void SetUp() override {
atomic_reference_ =
std::make_unique<AtomicReferenceImpl<base::UnguessableToken>>(
initial_value_);
}
base::UnguessableToken initial_value_;
private:
DISALLOW_COPY_AND_ASSIGN(UnguessableTokenAtomicReferenceImplTest);
};
TEST_F(UnguessableTokenAtomicReferenceImplTest, GetOnSameThread) {
VerifyValue(initial_value_);
}
TEST_F(UnguessableTokenAtomicReferenceImplTest, SetGetOnSameThread) {
base::UnguessableToken new_token = base::UnguessableToken::Create();
SetValue(new_token);
VerifyValue(new_token);
}
TEST_F(UnguessableTokenAtomicReferenceImplTest, SetOnNewThread) {
base::Thread thread("AtomicReferenceImplTest.SetOnNewThread");
EXPECT_TRUE(thread.Start());
base::UnguessableToken new_thread_token = base::UnguessableToken::Create();
SetValueInThread(thread, new_thread_token);
TinyTimeout();
VerifyValue(new_thread_token);
}
TEST_F(UnguessableTokenAtomicReferenceImplTest, GetOnNewThread) {
base::Thread thread("AtomicReferenceImplTest.GetOnNewThread");
EXPECT_TRUE(thread.Start());
base::UnguessableToken new_token = base::UnguessableToken::Create();
SetValue(new_token);
VerifyValueInThread(thread, new_token);
}
} // namespace nearby
} // namespace chromeos
......@@ -6,6 +6,8 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
static_library("library") {
sources = [
"atomic_boolean.h",
"atomic_reference.h",
"byte_array.h",
"count_down_latch.h",
"exception.h",
......
// Copyright (c) 2018 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 CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_BOOLEAN_H_
#define CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_BOOLEAN_H_
namespace location {
namespace nearby {
// A boolean value that may be updated atomically.
//
// https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicBoolean.html
class AtomicBoolean {
public:
virtual ~AtomicBoolean() {}
virtual bool get() = 0;
virtual void set(bool value) = 0;
};
} // namespace nearby
} // namespace location
#endif // CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_BOOLEAN_H__
// Copyright (c) 2018 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 CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_REFERENCE_H_
#define CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_REFERENCE_H_
namespace location {
namespace nearby {
// An object reference that may be updated atomically.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicReference.html
template <typename T>
class AtomicReference {
public:
virtual ~AtomicReference() {}
virtual T get() = 0;
virtual void set(T value) = 0;
};
} // namespace nearby
} // namespace location
#endif // CHROMEOS_COMPONENTS_NEARBY_LIBRARY_ATOMIC_REFERENCE_H__
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