blob: 22f2fbe184e4094b8a985dee3979635de19ab01f [file] [log] [blame]
// 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 "base/macros.h"
#include "base/optional.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "chromeos/components/nearby/library/exception.h"
#include "chromeos/components/nearby/library/settable_future.h"
namespace chromeos {
namespace nearby {
// Concrete location::nearby::SettableFuture implementation.
template <typename T>
class SettableFutureImpl : public location::nearby::SettableFuture<T> {
SettableFutureImpl() = default;
~SettableFutureImpl() override = default;
// This method will unblock any outstanding calls to get(), causing them to
// return |value|. Any future calls to get() will also return |value|. This
// operation can only successfully run one time, and subsequent calls will
// return false and will not update the ExceptionOr returned to get()ers.
bool SetExceptionOr(const location::nearby::ExceptionOr<T>& value) {
base::AutoLock al(set_value_lock_);
if (!value_has_been_set_.IsSignaled()) {
value_ = value;
return true;
return false;
friend class SettableFutureImplTest;
// location::nearby::Future:
location::nearby::ExceptionOr<T> get() override {
if (!value_has_been_set_.IsSignaled())
return *value_;
// location::nearby::SettableFuture:
bool set(T value) override {
return SetExceptionOr(location::nearby::ExceptionOr<T>(value));
base::Optional<location::nearby::ExceptionOr<T>> value_;
// This Lock is used to make sure that within set(), setting |value_| and
// signaling |value_has_been_set_| happens atomically, such that subsequent
// calls to set() will be guaranteed to neither set |value_| nor Signal().
base::Lock set_value_lock_;
base::WaitableEvent value_has_been_set_;
} // namespace nearby
} // namespace chromeos