-
Notifications
You must be signed in to change notification settings - Fork 879
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8118 from brave/ksmith-ledger-context
Add AsyncResult and BATLedgerContext classes to bat-native-ledger
- Loading branch information
Showing
15 changed files
with
838 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
vendor/bat-native-ledger/src/bat/ledger/internal/core/async_result.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* Copyright (c) 2021 The Brave Authors. All rights reserved. | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#ifndef BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_CORE_ASYNC_RESULT_H_ | ||
#define BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_CORE_ASYNC_RESULT_H_ | ||
|
||
#include <list> | ||
#include <memory> | ||
#include <utility> | ||
|
||
#include "base/callback.h" | ||
#include "base/optional.h" | ||
#include "base/threading/sequenced_task_runner_handle.h" | ||
|
||
namespace ledger { | ||
|
||
// Represents the result of an asynchronous operation. | ||
// | ||
// Example: | ||
// AsyncResult<int>::Resolver resolver; | ||
// resolver.Complete(42); | ||
// | ||
// AsyncResult<int> result = resolver.result(); | ||
// result.Listen(base::BindOnce([](const int& value) {})); | ||
// | ||
// Listeners are called on the current SequencedTaskRunner, and are guaranteed | ||
// to be called asynchronously. AsyncResult and Resolver objects are internally | ||
// reference counted and can be passed between sequences; the internal data | ||
// structures are updated on the sequence that created the Resolver. | ||
template <typename T> | ||
class AsyncResult { | ||
public: | ||
using CompleteType = T; | ||
using CompleteCallback = base::OnceCallback<void(const T&)>; | ||
|
||
void Listen(CompleteCallback on_complete) { | ||
Listener listener = {.on_complete = std::move(on_complete), | ||
.task_runner = base::SequencedTaskRunnerHandle::Get()}; | ||
|
||
task_runner_->PostTask(FROM_HERE, base::BindOnce(AddListenerInTask, store_, | ||
std::move(listener))); | ||
} | ||
|
||
class Resolver { | ||
public: | ||
Resolver() {} | ||
void Complete(T&& value) { result_.Complete(std::move(value)); } | ||
AsyncResult result() const { return result_; } | ||
|
||
private: | ||
AsyncResult result_; | ||
}; | ||
|
||
private: | ||
AsyncResult() | ||
: store_(new Store()), | ||
task_runner_(base::SequencedTaskRunnerHandle::Get()) {} | ||
|
||
enum class State { kPending, kComplete }; | ||
|
||
struct Listener { | ||
CompleteCallback on_complete; | ||
scoped_refptr<base::SequencedTaskRunner> task_runner; | ||
}; | ||
|
||
struct Store { | ||
Store() {} | ||
State state = State::kPending; | ||
base::Optional<T> value; | ||
std::list<Listener> listeners; | ||
}; | ||
|
||
void Complete(T&& value) { | ||
task_runner_->PostTask( | ||
FROM_HERE, base::BindOnce(SetCompleteInTask, store_, std::move(value))); | ||
} | ||
|
||
static void AddListenerInTask(std::shared_ptr<Store> store, | ||
Listener listener) { | ||
switch (store->state) { | ||
case State::kComplete: | ||
listener.task_runner->PostTask( | ||
FROM_HERE, base::BindOnce(RunCompleteCallback, store, | ||
std::move(listener.on_complete))); | ||
break; | ||
case State::kPending: | ||
store->listeners.emplace_back(std::move(listener)); | ||
break; | ||
} | ||
} | ||
|
||
static void SetCompleteInTask(std::shared_ptr<Store> store, T value) { | ||
if (store->state != State::kPending) | ||
return; | ||
|
||
store->state = State::kComplete; | ||
store->value = std::move(value); | ||
|
||
for (auto& listener : store->listeners) { | ||
listener.task_runner->PostTask( | ||
FROM_HERE, base::BindOnce(RunCompleteCallback, store, | ||
std::move(listener.on_complete))); | ||
} | ||
|
||
store->listeners.clear(); | ||
} | ||
|
||
static void RunCompleteCallback(std::shared_ptr<Store> store, | ||
CompleteCallback on_complete) { | ||
DCHECK(store->value); | ||
std::move(on_complete).Run(*store->value); | ||
} | ||
|
||
std::shared_ptr<Store> store_; | ||
scoped_refptr<base::SequencedTaskRunner> task_runner_; | ||
}; | ||
|
||
} // namespace ledger | ||
|
||
#endif // BRAVE_VENDOR_BAT_NATIVE_LEDGER_SRC_BAT_LEDGER_INTERNAL_CORE_ASYNC_RESULT_H_ |
40 changes: 40 additions & 0 deletions
40
vendor/bat-native-ledger/src/bat/ledger/internal/core/async_result_unittest.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* Copyright (c) 2021 The Brave Authors. All rights reserved. | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include "bat/ledger/internal/core/async_result.h" | ||
#include "base/test/bind.h" | ||
#include "base/test/task_environment.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
namespace ledger { | ||
|
||
class AsyncResultTest : public testing::Test { | ||
protected: | ||
base::test::TaskEnvironment task_environment_; | ||
}; | ||
|
||
TEST_F(AsyncResultTest, CompleteResultSentInFutureTurn) { | ||
AsyncResult<int>::Resolver resolver; | ||
resolver.Complete(10); | ||
int value = 0; | ||
resolver.result().Listen( | ||
base::BindLambdaForTesting([&value](const int& v) { value = v; })); | ||
ASSERT_EQ(value, 0); | ||
task_environment_.RunUntilIdle(); | ||
ASSERT_EQ(value, 10); | ||
} | ||
|
||
TEST_F(AsyncResultTest, CompleteCallbacksExecutedInFutureTurn) { | ||
AsyncResult<int>::Resolver resolver; | ||
int value = 0; | ||
resolver.result().Listen( | ||
base::BindLambdaForTesting([&value](const int& v) { value = v; })); | ||
resolver.Complete(1); | ||
ASSERT_EQ(value, 0); | ||
task_environment_.RunUntilIdle(); | ||
ASSERT_EQ(value, 1); | ||
} | ||
|
||
} // namespace ledger |
95 changes: 95 additions & 0 deletions
95
vendor/bat-native-ledger/src/bat/ledger/internal/core/bat_ledger_context.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/* Copyright (c) 2021 The Brave Authors. All rights reserved. | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
#include "bat/ledger/internal/core/bat_ledger_context.h" | ||
|
||
#include <utility> | ||
|
||
#include "bat/ledger/internal/ledger_impl.h" | ||
#include "bat/ledger/ledger_client.h" | ||
|
||
namespace ledger { | ||
|
||
namespace { | ||
|
||
size_t g_next_component_key = 0; | ||
|
||
} // namespace | ||
|
||
BATLedgerContext::BATLedgerContext(LedgerImpl* ledger_impl) | ||
: ledger_client_(ledger_impl->ledger_client()), ledger_impl_(ledger_impl) { | ||
DCHECK(ledger_client_); | ||
} | ||
|
||
BATLedgerContext::BATLedgerContext(LedgerClient* ledger_client) | ||
: ledger_client_(ledger_client) { | ||
DCHECK(ledger_client_); | ||
} | ||
|
||
BATLedgerContext::~BATLedgerContext() = default; | ||
|
||
using Component = BATLedgerContext::Component; | ||
using ComponentKey = BATLedgerContext::ComponentKey; | ||
|
||
ComponentKey::ComponentKey() : value_(g_next_component_key++) {} | ||
|
||
Component::Component(BATLedgerContext* context) : context_(context) {} | ||
|
||
Component::~Component() = default; | ||
|
||
using LogStream = BATLedgerContext::LogStream; | ||
|
||
LogStream::LogStream(BATLedgerContext* context, | ||
base::Location location, | ||
LogLevel log_level) | ||
: context_(context), location_(location), log_level_(log_level) {} | ||
|
||
LogStream::LogStream(LogStream&& other) | ||
: context_(other.context_), | ||
location_(other.location_), | ||
log_level_(other.log_level_), | ||
stream_(std::move(other.stream_)) { | ||
other.moved_ = true; | ||
} | ||
|
||
LogStream& LogStream::operator=(LogStream&& other) { | ||
context_ = other.context_; | ||
location_ = other.location_; | ||
log_level_ = other.log_level_; | ||
stream_ = std::move(other.stream_); | ||
|
||
other.moved_ = true; | ||
return *this; | ||
} | ||
|
||
LogStream::~LogStream() { | ||
if (!moved_) { | ||
context_->GetLedgerClient()->Log( | ||
location_.file_name(), location_.line_number(), | ||
static_cast<int>(log_level_), stream_.str()); | ||
} | ||
} | ||
|
||
LogStream BATLedgerContext::Log(base::Location location, LogLevel log_level) { | ||
return LogStream(this, location, log_level); | ||
} | ||
|
||
LogStream BATLedgerContext::LogError(base::Location location) { | ||
return LogStream(this, location, LogLevel::kError); | ||
} | ||
|
||
LogStream BATLedgerContext::LogInfo(base::Location location) { | ||
return LogStream(this, location, LogLevel::kInfo); | ||
} | ||
|
||
LogStream BATLedgerContext::LogVerbose(base::Location location) { | ||
return LogStream(this, location, LogLevel::kVerbose); | ||
} | ||
|
||
LogStream BATLedgerContext::LogFull(base::Location location) { | ||
return LogStream(this, location, LogLevel::kFull); | ||
} | ||
|
||
} // namespace ledger |
Oops, something went wrong.