nearby: snapshot of cl/313536507

Signed-off-by: Alexey Polyudov <apolyudov@google.com>
Change-Id: I8936b527079074d5c3af5531b9245063767cc4a7
This commit is contained in:
Alexey Polyudov
2020-05-28 00:03:22 -07:00
parent 667bf4ee3b
commit ae1c427b99
334 changed files with 20315 additions and 1487 deletions
+57
View File
@@ -0,0 +1,57 @@
cc_library(
name = "g3",
srcs = [
"atomic_boolean.h",
"atomic_reference_any.h",
"bluetooth_adapter.cc",
"bluetooth_adapter.h",
"condition_variable.h",
"count_down_latch.h",
"medium_environment.cc",
"medium_environment.h",
"multi_thread_executor.h",
"mutex.h",
"platform.cc",
"scheduled_executor.cc",
"scheduled_executor.h",
"settable_future_any.h",
"single_thread_executor.h",
"system_clock.cc",
],
visibility = [
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
"//core_v2:__subpackages__",
"//platform_v2:__subpackages__",
],
deps = [
":crypto", # build_cleaner: keep
"//platform_v2/api",
"//platform_v2/base",
"//platform_v2/impl/shared:posix_mutex",
"//absl/base:core_headers",
"//absl/container:flat_hash_map",
"//absl/container:flat_hash_set",
"//absl/memory",
"//absl/strings",
"//absl/synchronization",
"//absl/time",
"//absl/types:any",
"//thread",
],
)
cc_library(
name = "crypto",
srcs = [
"crypto.cc",
],
visibility = [
"//platform_v2/g3:__pkg__",
],
deps = [
"//platform_v2/api",
"//platform_v2/base",
"//absl/strings",
"//openssl:crypto",
],
)
+30
View File
@@ -0,0 +1,30 @@
#ifndef PLATFORM_V2_IMPL_G3_ATOMIC_BOOLEAN_H_
#define PLATFORM_V2_IMPL_G3_ATOMIC_BOOLEAN_H_
#include <atomic>
#include "platform_v2/api/atomic_boolean.h"
namespace location {
namespace nearby {
namespace g3 {
// See documentation in
// https://source.corp.google.com/piper///depot/google3/platform_v2/api/atomic_boolean.h
class AtomicBoolean : public api::AtomicBoolean {
public:
explicit AtomicBoolean(bool initial_value) : value_(initial_value) {}
~AtomicBoolean() override = default;
bool Get() const override { return value_.load(); }
bool Set(bool value) override { return value_.exchange(value); }
private:
std::atomic_bool value_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_ATOMIC_BOOLEAN_H_
@@ -0,0 +1,46 @@
#ifndef PLATFORM_V2_IMPL_G3_ATOMIC_REFERENCE_ANY_H_
#define PLATFORM_V2_IMPL_G3_ATOMIC_REFERENCE_ANY_H_
#include "platform_v2/api/atomic_reference.h"
#include "absl/base/integral_types.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/any.h"
namespace location {
namespace nearby {
namespace g3 {
// Provide implementation for absl::any.
class AtomicReferenceAny : public api::AtomicReference<absl::any> {
public:
explicit AtomicReferenceAny(absl::any initial_value)
: value_(std::move(initial_value)) {}
~AtomicReferenceAny() override = default;
absl::any Get() const & override {
absl::MutexLock lock(&mutex_);
return value_;
}
absl::any Get() && override {
absl::MutexLock lock(&mutex_);
return std::move(value_);
}
void Set(const absl::any& value) override {
absl::MutexLock lock(&mutex_);
value_ = value;
}
void Set(absl::any&& value) override {
absl::MutexLock lock(&mutex_);
value_ = std::move(value);
}
private:
mutable absl::Mutex mutex_;
absl::any value_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_ATOMIC_REFERENCE_ANY_H_
@@ -0,0 +1,65 @@
#include "platform_v2/impl/g3/bluetooth_adapter.h"
#include <string>
#include "platform_v2/impl/g3/medium_environment.h"
namespace location {
namespace nearby {
namespace g3 {
BluetoothDevice::BluetoothDevice(BluetoothAdapter* adapter)
: adapter_(*adapter) {}
std::string BluetoothDevice::GetName() const { return adapter_.GetName(); }
bool BluetoothAdapter::SetStatus(Status status) ABSL_LOCKS_EXCLUDED(mutex_) {
absl::MutexLock lock(&mutex_);
enabled_ = (status == Status::kEnabled);
RunOnCallbackThread([this]() {
auto& env = MediumEnvironment::Instance();
env.OnBluetoothAdapterChangedState(*this);
});
return true;
}
bool BluetoothAdapter::IsEnabled() const {
absl::MutexLock lock(&mutex_);
return enabled_;
}
BluetoothAdapter::ScanMode BluetoothAdapter::GetScanMode() const {
absl::MutexLock lock(&mutex_);
return mode_;
}
bool BluetoothAdapter::SetScanMode(BluetoothAdapter::ScanMode mode) {
absl::MutexLock lock(&mutex_);
if (enabled_) return false;
mode_ = mode;
RunOnCallbackThread([this]() {
auto& env = MediumEnvironment::Instance();
env.OnBluetoothAdapterChangedState(*this);
});
return true;
}
std::string BluetoothAdapter::GetName() const {
absl::MutexLock lock(&mutex_);
return name_;
}
bool BluetoothAdapter::SetName(absl::string_view name) {
absl::MutexLock lock(&mutex_);
if (enabled_) return false;
name_ = name;
RunOnCallbackThread([this]() {
auto& env = MediumEnvironment::Instance();
env.OnBluetoothAdapterChangedState(*this);
});
return true;
}
} // namespace g3
} // namespace nearby
} // namespace location
@@ -0,0 +1,90 @@
#ifndef PLATFORM_V2_IMPL_G3_BLUETOOTH_ADAPTER_H_
#define PLATFORM_V2_IMPL_G3_BLUETOOTH_ADAPTER_H_
#include <string>
#include "platform_v2/api/bluetooth_adapter.h"
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/impl/g3/single_thread_executor.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
namespace location {
namespace nearby {
namespace g3 {
// BluetoothDevice and BluetoothAdapter have a mutual dependency.
class BluetoothAdapter;
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice : public api::BluetoothDevice {
public:
~BluetoothDevice() override = default;
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
std::string GetName() const override;
BluetoothAdapter& GetAdapter();
private:
// Only BluetoothAdapter may instantiate BluetoothDevice.
friend class BluetoothAdapter;
explicit BluetoothDevice(BluetoothAdapter* adapter);
BluetoothAdapter& adapter_;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
class BluetoothAdapter : public api::BluetoothAdapter {
public:
using Status = api::BluetoothAdapter::Status;
using ScanMode = api::BluetoothAdapter::ScanMode;
BluetoothAdapter() = default;
~BluetoothAdapter() override = default;
// Synchronously sets the status of the BluetoothAdapter to 'status', and
// returns true if the operation was a success.
bool SetStatus(Status status) override ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if the BluetoothAdapter's current status is
// Status::Value::kEnabled.
bool IsEnabled() const override ABSL_LOCKS_EXCLUDED(mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode()
//
// Returns ScanMode::kUnknown on error.
ScanMode GetScanMode() const override ABSL_LOCKS_EXCLUDED(mutex_);
// Synchronously sets the scan mode of the adapter, and returns true if the
// operation was a success.
bool SetScanMode(ScanMode mode) override ABSL_LOCKS_EXCLUDED(mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
// Returns an empty string on error
std::string GetName() const override ABSL_LOCKS_EXCLUDED(mutex_);
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
bool SetName(absl::string_view name) override ABSL_LOCKS_EXCLUDED(mutex_);
BluetoothDevice& GetDevice() { return device_; }
private:
void RunOnCallbackThread(std::function<void()> runnable) {
serial_executor_.Execute(std::move(runnable));
}
mutable absl::Mutex mutex_;
BluetoothDevice device_{this};
ScanMode mode_ ABSL_GUARDED_BY(mutex_) = ScanMode::kNone;
std::string name_ ABSL_GUARDED_BY(mutex_) = "unknown G3 BT device";
bool enabled_ ABSL_GUARDED_BY(mutex_) = false;
SingleThreadExecutor serial_executor_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_BLUETOOTH_ADAPTER_H_
@@ -0,0 +1,33 @@
#ifndef PLATFORM_V2_IMPL_G3_CONDITION_VARIABLE_H_
#define PLATFORM_V2_IMPL_G3_CONDITION_VARIABLE_H_
#include "platform_v2/api/condition_variable.h"
#include "platform_v2/base/exception.h"
#include "platform_v2/impl/g3/mutex.h"
#include "absl/synchronization/mutex.h"
namespace location {
namespace nearby {
namespace g3 {
class ConditionVariable : public api::ConditionVariable {
public:
explicit ConditionVariable(g3::Mutex* mutex) : mutex_(&mutex->mutex_) {}
~ConditionVariable() override = default;
Exception Wait() override {
cond_var_.Wait(mutex_);
return {Exception::kSuccess};
}
void Notify() override { cond_var_.SignalAll(); }
private:
absl::Mutex* mutex_;
absl::CondVar cond_var_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_CONDITION_VARIABLE_H_
@@ -0,0 +1,59 @@
#ifndef PLATFORM_V2_IMPL_G3_COUNT_DOWN_LATCH_H_
#define PLATFORM_V2_IMPL_G3_COUNT_DOWN_LATCH_H_
#include "platform_v2/api/count_down_latch.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
namespace location {
namespace nearby {
namespace g3 {
// A synchronization aid that allows one or more threads to wait until a set of
// operations being performed in other threads completes.
//
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html
class CountDownLatch final : public api::CountDownLatch {
public:
explicit CountDownLatch(int count) : count_(count) {}
CountDownLatch(const CountDownLatch&) = delete;
CountDownLatch& operator=(const CountDownLatch&) = delete;
CountDownLatch(CountDownLatch&&) = delete;
CountDownLatch& operator=(CountDownLatch&&) = delete;
ExceptionOr<bool> Await(absl::Duration timeout) override {
absl::MutexLock lock(&mutex_);
absl::Time deadline = absl::Now() + timeout;
while (count_ > 0) {
if (cond_.WaitWithDeadline(&mutex_, deadline)) {
return ExceptionOr<bool>(false);
}
}
return ExceptionOr<bool>(true);
}
Exception Await() override {
absl::MutexLock lock(&mutex_);
while (count_ > 0) {
cond_.Wait(&mutex_);
}
return {Exception::kSuccess};
}
void CountDown() override {
absl::MutexLock lock(&mutex_);
if (count_ > 0 && --count_ == 0) {
cond_.SignalAll();
}
}
private:
absl::Mutex mutex_; // Mutex to be used with cond_.Wait...() method family.
absl::CondVar cond_; // Condition to synchronize up to N waiting threads.
int count_
ABSL_GUARDED_BY(mutex_); // When zero, latch should release all waiters.
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_COUNT_DOWN_LATCH_H_
+39
View File
@@ -0,0 +1,39 @@
#include "platform_v2/api/crypto.h"
#include <cstdint>
#include <string>
#include "platform_v2/base/byte_array.h"
#include "absl/strings/string_view.h"
#include "openssl/digest.h"
namespace location {
namespace nearby {
// Initialize global crypto state.
void Crypto::Init() {}
static ByteArray Hash(absl::string_view input, const EVP_MD* algo) {
unsigned int md_out_size = EVP_MAX_MD_SIZE;
uint8_t digest_buffer[EVP_MAX_MD_SIZE];
if (input.empty()) return {};
if (!EVP_Digest(input.data(), input.size(), digest_buffer, &md_out_size, algo,
nullptr))
return {};
return ByteArray{reinterpret_cast<char*>(digest_buffer), md_out_size};
}
// Return MD5 hash of input.
ByteArray Crypto::Md5(absl::string_view input) {
return Hash(input, EVP_md5());
}
// Return SHA256 hash of input.
ByteArray Crypto::Sha256(absl::string_view input) {
return Hash(input, EVP_sha256());
}
} // namespace nearby
} // namespace location
@@ -0,0 +1,32 @@
#include "platform_v2/impl/g3/medium_environment.h"
namespace location {
namespace nearby {
namespace g3 {
MediumEnvironment& MediumEnvironment::Instance() {
static std::aligned_storage_t<sizeof(MediumEnvironment),
alignof(MediumEnvironment)>
storage;
static MediumEnvironment* env = new (&storage) MediumEnvironment();
return *env;
}
void MediumEnvironment::Reset() {
absl::MutexLock lock(&mutex_);
bluetooth_adapters_.clear();
}
void MediumEnvironment::OnBluetoothAdapterChangedState(
BluetoothAdapter& adapter) {
absl::MutexLock lock(&mutex_);
// We don't care if there is an adapter already since all we store is a
// pointer.
bluetooth_adapters_.emplace(&adapter);
// TODO(apolyudov): Add event propagation code when Medium registration is
// implemented.
}
} // namespace g3
} // namespace nearby
} // namespace location
@@ -0,0 +1,47 @@
#ifndef PLATFORM_V2_IMPL_G3_MEDIUM_ENVIRONMENT_H_
#define PLATFORM_V2_IMPL_G3_MEDIUM_ENVIRONMENT_H_
#include <new>
#include <string>
#include <type_traits>
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/impl/g3/bluetooth_adapter.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/synchronization/mutex.h"
namespace location {
namespace nearby {
namespace g3 {
// MediumEnvironment is a simulated environment which allowes multiple instances
// of simulated HW devices to "work" together as if they are physical.
// For each medium type it provides necessary methods to implement
// advertising, discovery and establishment of a data link.
class MediumEnvironment {
public:
~MediumEnvironment() = default;
// Singleton constructor/accessor.
static MediumEnvironment& Instance();
// Clear state. No notifications are sent.
void Reset() ABSL_LOCKS_EXCLUDED(mutex_);
// Add an adapter to internal container.
// Notify BluetoothClassicMediums if any that adapter state has changed.
void OnBluetoothAdapterChangedState(BluetoothAdapter& adapter)
ABSL_LOCKS_EXCLUDED(mutex_);
private:
MediumEnvironment() = default;
absl::Mutex mutex_;
absl::flat_hash_set<BluetoothAdapter*> bluetooth_adapters_
ABSL_GUARDED_BY(mutex_);
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_MEDIUM_ENVIRONMENT_H_
@@ -0,0 +1,54 @@
#ifndef PLATFORM_V2_IMPL_G3_MULTI_THREAD_EXECUTOR_H_
#define PLATFORM_V2_IMPL_G3_MULTI_THREAD_EXECUTOR_H_
#include <atomic>
#include "platform_v2/api/submittable_executor.h"
#include "platform_v2/impl/g3/count_down_latch.h"
#include "absl/time/clock.h"
#include "thread/threadpool.h"
namespace location {
namespace nearby {
namespace g3 {
// An Executor that reuses a fixed number of threads operating off a shared
// unbounded queue.
class MultiThreadExecutor : public api::SubmittableExecutor {
public:
explicit MultiThreadExecutor(int max_parallelism)
: thread_pool_(max_parallelism) {
thread_pool_.StartWorkers();
}
void Execute(Runnable&& runnable) override {
if (!shutdown_) {
thread_pool_.Schedule(std::move(runnable));
}
}
bool DoSubmit(Runnable&& runnable) override {
if (shutdown_) return false;
thread_pool_.Schedule(std::move(runnable));
return true;
}
void Shutdown() override { DoShutdown(); }
~MultiThreadExecutor() override { DoShutdown(); }
void ScheduleAfter(absl::Duration delay, Runnable&& runnable) {
if (shutdown_) return;
thread_pool_.ScheduleAt(absl::Now() + delay, std::move(runnable));
}
bool InShutdown() const { return shutdown_; }
private:
void DoShutdown() {
shutdown_ = true;
}
std::atomic_bool shutdown_ = false;
ThreadPool thread_pool_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_MULTI_THREAD_EXECUTOR_H_
+47
View File
@@ -0,0 +1,47 @@
#ifndef PLATFORM_V2_IMPL_G3_MUTEX_H_
#define PLATFORM_V2_IMPL_G3_MUTEX_H_
#include "platform_v2/api/mutex.h"
#include "platform_v2/impl/shared/posix_mutex.h"
#include "absl/synchronization/mutex.h"
namespace location {
namespace nearby {
namespace g3 {
class ABSL_LOCKABLE Mutex : public api::Mutex {
public:
explicit Mutex(bool check) : check_(check) {}
~Mutex() override = default;
Mutex(Mutex&&) = delete;
Mutex& operator=(Mutex&&) = delete;
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() override {
mutex_.Lock();
if (!check_) mutex_.ForgetDeadlockInfo();
}
void Unlock() ABSL_UNLOCK_FUNCTION() override { mutex_.Unlock(); }
private:
friend class ConditionVariable;
absl::Mutex mutex_;
bool check_;
};
class ABSL_LOCKABLE RecursiveMutex : public posix::Mutex {
public:
~RecursiveMutex() override = default;
RecursiveMutex() = default;
RecursiveMutex(RecursiveMutex&&) = delete;
RecursiveMutex& operator=(RecursiveMutex&&) = delete;
RecursiveMutex(const RecursiveMutex&) = delete;
RecursiveMutex& operator=(const RecursiveMutex&) = delete;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_MUTEX_H_
+30
View File
@@ -0,0 +1,30 @@
#ifndef PLATFORM_V2_IMPL_G3_PIPE_H_
#define PLATFORM_V2_IMPL_G3_PIPE_H_
#include <memory>
#include "platform_v2/base/base_pipe.h"
#include "platform_v2/impl/g3/condition_variable.h"
#include "platform_v2/impl/g3/mutex.h"
namespace location {
namespace nearby {
namespace g3 {
class Pipe : public BasePipe {
public:
Pipe() {
auto mutex = std::make_unique<g3::Mutex>(/*check=*/true);
auto cond = std::make_unique<g3::ConditionVariable>(mutex.get());
Setup(std::move(mutex), std::move(cond));
}
~Pipe() override = default;
Pipe(Pipe &&) = delete;
Pipe& operator=(Pipe&&) = delete;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_PIPE_H_
+136
View File
@@ -0,0 +1,136 @@
#include "platform_v2/api/platform.h"
#include <atomic>
#include <memory>
#include "platform_v2/api/atomic_boolean.h"
#include "platform_v2/api/atomic_reference.h"
#include "platform_v2/api/ble.h"
#include "platform_v2/api/ble_v2.h"
#include "platform_v2/api/bluetooth_adapter.h"
#include "platform_v2/api/bluetooth_classic.h"
#include "platform_v2/api/condition_variable.h"
#include "platform_v2/api/count_down_latch.h"
#include "platform_v2/api/mutex.h"
#include "platform_v2/api/scheduled_executor.h"
#include "platform_v2/api/server_sync.h"
#include "platform_v2/api/settable_future.h"
#include "platform_v2/api/submittable_executor.h"
#include "platform_v2/api/webrtc.h"
#include "platform_v2/api/wifi.h"
#include "platform_v2/impl/g3/atomic_boolean.h"
#include "platform_v2/impl/g3/atomic_reference_any.h"
#include "platform_v2/impl/g3/bluetooth_adapter.h"
#include "platform_v2/impl/g3/condition_variable.h"
#include "platform_v2/impl/g3/count_down_latch.h"
#include "platform_v2/impl/g3/multi_thread_executor.h"
#include "platform_v2/impl/g3/mutex.h"
#include "platform_v2/impl/g3/scheduled_executor.h"
#include "platform_v2/impl/g3/settable_future_any.h"
#include "platform_v2/impl/g3/single_thread_executor.h"
#include "absl/base/integral_types.h"
#include "absl/memory/memory.h"
#include "absl/time/time.h"
namespace location {
namespace nearby {
namespace api {
std::unique_ptr<SubmittableExecutor>
ImplementationPlatform::CreateSingleThreadExecutor() {
return absl::make_unique<g3::SingleThreadExecutor>();
}
std::unique_ptr<SubmittableExecutor>
ImplementationPlatform::CreateMultiThreadExecutor(int max_concurrency) {
return absl::make_unique<g3::MultiThreadExecutor>(max_concurrency);
}
std::unique_ptr<ScheduledExecutor>
ImplementationPlatform::CreateScheduledExecutor() {
return absl::make_unique<g3::ScheduledExecutor>();
}
std::unique_ptr<AtomicReference<absl::any>>
ImplementationPlatform::CreateAtomicReferenceAny(absl::any initial_value) {
return absl::make_unique<g3::AtomicReferenceAny>(initial_value);
}
std::unique_ptr<SettableFuture<absl::any>>
ImplementationPlatform::CreateSettableFutureAny() {
return absl::make_unique<g3::SettableFutureAny>();
}
std::unique_ptr<BluetoothAdapter>
ImplementationPlatform::CreateBluetoothAdapter() {
return absl::make_unique<g3::BluetoothAdapter>();
}
std::unique_ptr<CountDownLatch> ImplementationPlatform::CreateCountDownLatch(
std::int32_t count) {
return absl::make_unique<g3::CountDownLatch>(count);
}
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(
bool initial_value) {
return absl::make_unique<g3::AtomicBoolean>(initial_value);
}
std::unique_ptr<BluetoothClassicMedium>
ImplementationPlatform::CreateBluetoothClassicMedium() {
return std::unique_ptr<BluetoothClassicMedium>();
}
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium() {
return std::unique_ptr<BleMedium>();
}
std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium() {
return std::unique_ptr<ble_v2::BleMedium>();
}
std::unique_ptr<ServerSyncMedium>
ImplementationPlatform::CreateServerSyncMedium() {
return std::unique_ptr<ServerSyncMedium>(/*new ServerSyncMediumImpl()*/);
}
std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() {
return std::unique_ptr<WifiMedium>();
}
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
return std::unique_ptr<WifiLanMedium>();
}
std::unique_ptr<WebRtcSignalingMessenger>
ImplementationPlatform::CreateWebRtcSignalingMessenger(
absl::string_view self_id) {
return std::unique_ptr<WebRtcSignalingMessenger>(
/*new FCMSignalingMessenger()*/);
}
std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) {
if (mode == Mutex::Mode::kRecursive)
return absl::make_unique<g3::RecursiveMutex>();
else
return absl::make_unique<g3::Mutex>(mode == Mutex::Mode::kRegular);
}
std::unique_ptr<ConditionVariable>
ImplementationPlatform::CreateConditionVariable(Mutex* mutex) {
return std::unique_ptr<ConditionVariable>(
new g3::ConditionVariable(static_cast<g3::Mutex*>(mutex)));
}
std::string ImplementationPlatform::GetDeviceId() {
// TODO(alexchau): Get deviceId from base
return "google3";
}
std::string ImplementationPlatform::GetPayloadPath(int64_t payload_id) {
return "/tmp/" + std::to_string(payload_id);
}
} // namespace api
} // namespace nearby
} // namespace location
@@ -0,0 +1,65 @@
#include "platform_v2/impl/g3/scheduled_executor.h"
#include <atomic>
#include <memory>
#include "platform_v2/api/cancelable.h"
#include "platform_v2/base/runnable.h"
#include "absl/time/clock.h"
namespace location {
namespace nearby {
namespace g3 {
namespace {
class ScheduledCancelable : public api::Cancelable {
public:
bool Cancel() override {
Status expected = kNotRun;
while (expected == kNotRun) {
if (status_.compare_exchange_strong(expected, kCanceled)) {
return true;
}
}
return false;
}
bool MarkExecuted() {
Status expected = kNotRun;
while (expected == kNotRun) {
if (status_.compare_exchange_strong(expected, kExecuted)) {
return true;
}
}
return false;
}
private:
enum Status {
kNotRun,
kExecuted,
kCanceled,
};
std::atomic<Status> status_ = kNotRun;
};
} // namespace
std::shared_ptr<api::Cancelable> ScheduledExecutor::Schedule(
Runnable&& runnable, absl::Duration delay) {
auto scheduled_cancelable = std::make_shared<ScheduledCancelable>();
if (executor_.InShutdown()) {
return scheduled_cancelable;
}
executor_.ScheduleAfter(
delay, [this, scheduled_cancelable, runnable(std::move(runnable))]() {
if (!executor_.InShutdown() && scheduled_cancelable->MarkExecuted()) {
runnable();
}
});
return scheduled_cancelable;
}
} // namespace g3
} // namespace nearby
} // namespace location
@@ -0,0 +1,42 @@
#ifndef PLATFORM_V2_IMPL_G3_SCHEDULED_EXECUTOR_H_
#define PLATFORM_V2_IMPL_G3_SCHEDULED_EXECUTOR_H_
#include <atomic>
#include <memory>
#include "platform_v2/api/cancelable.h"
#include "platform_v2/api/scheduled_executor.h"
#include "platform_v2/base/runnable.h"
#include "platform_v2/impl/g3/single_thread_executor.h"
#include "absl/time/clock.h"
#include "thread/threadpool.h"
namespace location {
namespace nearby {
namespace g3 {
// An Executor that reuses a fixed number of threads operating off a shared
// unbounded queue.
class ScheduledExecutor final : public api::ScheduledExecutor {
public:
ScheduledExecutor() = default;
~ScheduledExecutor() override {
executor_.Shutdown();
}
void Execute(Runnable&& runnable) override {
executor_.Execute(std::move(runnable));
}
std::shared_ptr<api::Cancelable> Schedule(Runnable&& runnable,
absl::Duration delay) override;
void Shutdown() override { executor_.Shutdown(); }
private:
SingleThreadExecutor executor_;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_SCHEDULED_EXECUTOR_H_
@@ -0,0 +1,104 @@
#ifndef PLATFORM_V2_IMPL_G3_SETTABLE_FUTURE_ANY_H_
#define PLATFORM_V2_IMPL_G3_SETTABLE_FUTURE_ANY_H_
#include <utility>
#include "platform_v2/api/platform.h"
#include "platform_v2/api/settable_future.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "absl/types/any.h"
namespace location {
namespace nearby {
namespace g3 {
class SettableFutureAny : public api::SettableFuture<absl::any> {
public:
SettableFutureAny() = default;
~SettableFutureAny() override = default;
bool Set(const absl::any& value) override {
absl::MutexLock lock(&mutex_);
if (!done_) {
value_ = value;
done_ = true;
exception_ = {Exception::kSuccess};
completed_.SignalAll();
}
return true;
}
bool Set(absl::any&& value) override {
absl::MutexLock lock(&mutex_);
if (!done_) {
value_ = std::move(value);
done_ = true;
exception_ = {Exception::kSuccess};
completed_.SignalAll();
}
return true;
}
bool SetException(Exception exception) override {
absl::MutexLock lock(&mutex_);
return SetExceptionLocked(exception);
}
void AddListener(Runnable runnable, api::Executor* executor) override {}
ExceptionOr<std::any> Get() override {
absl::MutexLock lock(&mutex_);
while (!done_) {
completed_.Wait(&mutex_);
}
return exception_.value != Exception::kSuccess
? ExceptionOr<std::any>{exception_.value}
: ExceptionOr<std::any>{value_};
}
ExceptionOr<std::any> Get(absl::Duration timeout) override {
absl::MutexLock lock(&mutex_);
while (!done_) {
absl::Time start_time = absl::Now();
if (completed_.WaitWithTimeout(&mutex_, timeout)) {
SetExceptionLocked({Exception::kTimeout});
break;
}
absl::Duration spent = absl::Now() - start_time;
if (spent < timeout) {
timeout -= spent;
} else if (!done_) {
SetExceptionLocked({Exception::kTimeout});
break;
}
}
return exception_.value != Exception::kSuccess
? ExceptionOr<std::any>{exception_.value}
: ExceptionOr<std::any>{value_};
}
private:
bool SetExceptionLocked(Exception exception) {
if (!done_) {
exception_ = exception.value != Exception::kSuccess
? exception
: Exception{Exception::kFailed};
done_ = true;
completed_.SignalAll();
}
return true;
}
absl::Mutex mutex_;
absl::CondVar completed_;
bool done_{false};
absl::any value_;
Exception exception_{Exception::kFailed};
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_SETTABLE_FUTURE_ANY_H_
@@ -0,0 +1,22 @@
#ifndef PLATFORM_V2_IMPL_G3_SINGLE_THREAD_EXECUTOR_H_
#define PLATFORM_V2_IMPL_G3_SINGLE_THREAD_EXECUTOR_H_
#include "platform_v2/impl/g3/multi_thread_executor.h"
namespace location {
namespace nearby {
namespace g3 {
// An Executor that uses a single worker thread operating off an unbounded
// queue.
class SingleThreadExecutor final : public MultiThreadExecutor {
public:
SingleThreadExecutor() : MultiThreadExecutor(1) {}
~SingleThreadExecutor() override = default;
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_G3_SINGLE_THREAD_EXECUTOR_H_
+16
View File
@@ -0,0 +1,16 @@
#include "platform_v2/api/system_clock.h"
#include "platform_v2/base/exception.h"
#include "absl/time/clock.h"
namespace location {
namespace nearby {
absl::Time SystemClock::ElapsedRealtime() { return absl::Now(); }
Exception SystemClock::Sleep(absl::Duration duration) {
absl::SleepFor(duration);
return {Exception::kSuccess};
}
} // namespace nearby
} // namespace location
+34
View File
@@ -0,0 +1,34 @@
cc_library(
name = "posix_mutex",
srcs = [
"posix_mutex.cc",
],
hdrs = [
"posix_mutex.h",
],
visibility = [
"//platform_v2/impl:__subpackages__",
],
deps = [
"//platform_v2/api",
"//platform_v2/base",
],
)
cc_library(
name = "posix_condition_variable",
srcs = [
"posix_condition_variable.cc",
],
hdrs = [
"posix_condition_variable.h",
],
visibility = [
"//platform_v2/impl:__subpackages__",
],
deps = [
":posix_mutex",
"//platform_v2/api",
"//platform_v2/base",
],
)
@@ -0,0 +1,30 @@
#include "platform_v2/impl/shared/posix_condition_variable.h"
namespace location {
namespace nearby {
namespace posix {
ConditionVariable::ConditionVariable(Mutex* mutex)
: mutex_(mutex), attr_(), cond_() {
pthread_condattr_init(&attr_);
pthread_cond_init(&cond_, &attr_);
}
ConditionVariable::~ConditionVariable() {
pthread_cond_destroy(&cond_);
pthread_condattr_destroy(&attr_);
}
void ConditionVariable::Notify() { pthread_cond_broadcast(&cond_); }
Exception ConditionVariable::Wait() {
pthread_cond_wait(&cond_, &(mutex_->mutex_));
return {Exception::kSuccess};
}
} // namespace posix
} // namespace nearby
} // namespace location
@@ -0,0 +1,31 @@
#ifndef PLATFORM_V2_IMPL_SHARED_POSIX_CONDITION_VARIABLE_H_
#define PLATFORM_V2_IMPL_SHARED_POSIX_CONDITION_VARIABLE_H_
#include <pthread.h>
#include "platform_v2/api/condition_variable.h"
#include "platform_v2/impl/shared/posix_mutex.h"
namespace location {
namespace nearby {
namespace posix {
class ConditionVariable : public api::ConditionVariable {
public:
explicit ConditionVariable(Mutex* mutex);
~ConditionVariable() override;
void Notify() override;
Exception Wait() override;
private:
Mutex* mutex_;
pthread_condattr_t attr_;
pthread_cond_t cond_;
};
} // namespace posix
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_SHARED_POSIX_CONDITION_VARIABLE_H_
@@ -0,0 +1,26 @@
#include "platform_v2/impl/shared/posix_mutex.h"
namespace location {
namespace nearby {
namespace posix {
Mutex::Mutex() : attr_(), mutex_() {
pthread_mutexattr_init(&attr_);
pthread_mutexattr_settype(&attr_, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mutex_, &attr_);
}
Mutex::~Mutex() {
pthread_mutex_destroy(&mutex_);
pthread_mutexattr_destroy(&attr_);
}
void Mutex::Lock() { pthread_mutex_lock(&mutex_); }
void Mutex::Unlock() { pthread_mutex_unlock(&mutex_); }
} // namespace posix
} // namespace nearby
} // namespace location
+31
View File
@@ -0,0 +1,31 @@
#ifndef PLATFORM_V2_IMPL_SHARED_POSIX_MUTEX_H_
#define PLATFORM_V2_IMPL_SHARED_POSIX_MUTEX_H_
#include <pthread.h>
#include "platform_v2/api/mutex.h"
namespace location {
namespace nearby {
namespace posix {
class ABSL_LOCKABLE Mutex : public api::Mutex {
public:
Mutex();
~Mutex() override;
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() override;
void Unlock() ABSL_UNLOCK_FUNCTION() override;
private:
friend class ConditionVariable;
pthread_mutexattr_t attr_;
pthread_mutex_t mutex_;
};
} // namespace posix
} // namespace nearby
} // namespace location
#endif // PLATFORM_V2_IMPL_SHARED_POSIX_MUTEX_H_