Skip to content

Commit

Permalink
feat: add keepThis keep lambda lifetime
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Sep 12, 2024
1 parent 38dedcf commit bb0b0bd
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 35 deletions.
18 changes: 8 additions & 10 deletions src-server/ll/core/Statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,13 @@ struct Statistics::Impl {
nlohmann::json json;

void submitData() {
auto charts = [](auto& self) -> coro::CoroTask<> {
coro::keepThis([&]() -> coro::CoroTask<> {
nlohmann::json pluginInfo;
pluginInfo["pluginName"] = getSelfModIns()->getName();
pluginInfo["customCharts"] = getCustomCharts();
self.json["plugins"].emplace_back(pluginInfo);
json["plugins"].emplace_back(pluginInfo);
co_return;
}(*this);
charts.syncLaunch(thread::ServerThreadExecutor::getDefault());
}).syncLaunch(thread::ServerThreadExecutor::getDefault());
try {
auto body = json.dump();
cpr::Post(
Expand Down Expand Up @@ -156,17 +155,16 @@ struct Statistics::Impl {
json["osVersion"] = "";
json["coreCount"] = std::thread::hardware_concurrency();

auto submit = [](auto& self) -> coro::CoroTask<> {
coro::keepThis([&]() -> coro::CoroTask<> {
co_await (1.0min * random_utils::rand(3.0, 6.0));
self.submitData();
submitData();
co_await (1.0min * random_utils::rand(1.0, 30.0));
self.submitData();
submitData();
while (true) {
co_await 30min;
self.submitData();
submitData();
}
}(*this);
submit.launch(thread::ThreadPoolExecutor::getDefault());
}).launch(thread::ThreadPoolExecutor::getDefault());
getLogger().info("Statistics has been enabled, you can disable statistics in configuration file"_tr());
}
};
Expand Down
16 changes: 8 additions & 8 deletions src/ll/api/coro/Collect.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ namespace ll::coro {
template <class Container>
struct CollectAllAwaiter {
public:
using ExpectedT = typename Container::value_type::ExpectedT;
using ExpectedResult = typename Container::value_type::ExpectedResult;

using allocator_type =
typename std::allocator_traits<typename Container::allocator_type>::template rebind_alloc<ExpectedT>;
typename std::allocator_traits<typename Container::allocator_type>::template rebind_alloc<ExpectedResult>;

private:
std::coroutine_handle<> handle;
Container tasks;
std::vector<ExpectedT, allocator_type> results;
std::atomic_size_t counter;
std::coroutine_handle<> handle;
Container tasks;
std::vector<ExpectedResult, allocator_type> results;
std::atomic_size_t counter;

public:
CollectAllAwaiter(const CollectAllAwaiter&) = delete;
Expand Down Expand Up @@ -56,7 +56,7 @@ template <template <class> class T, class... Ts>
class CollectAllTupleAwaiter {
public:
using Input = std::tuple<T<Ts>...>;
using Result = std::tuple<typename T<Ts>::ExpectedT...>;
using Result = std::tuple<typename T<Ts>::ExpectedResult...>;

private:
std::coroutine_handle<> handle;
Expand Down Expand Up @@ -92,7 +92,7 @@ class CollectAllTupleAwaiter {
}(std::get<I>(tasks), std::get<I>(results)),
...
);
}(std::make_index_sequence<sizeof...(Ts)>());
}(std::index_sequence_for<Ts...>());
}

constexpr auto await_resume() { return std::move(results); }
Expand Down
12 changes: 6 additions & 6 deletions src/ll/api/coro/CoroPromise.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ struct CoroPromiseBase {
};
template <class T>
struct CoroPromise : public CoroPromiseBase {
using ExpectedT = std::conditional_t<concepts::IsLeviExpected<T>, T, Expected<T>>;
using ExpectedResult = std::conditional_t<concepts::IsLeviExpected<T>, T, Expected<T>>;

ExpectedT result{};
ExpectedResult result{};

constexpr CoroPromise() noexcept = default;

template <class V>
void return_value(V&& value) noexcept(std::is_nothrow_constructible_v<T, V>)
requires(std::is_constructible_v<T, V>)
{
if constexpr (std::is_same_v<T, ExpectedT>) {
result = T{std::forward<V>(value)};
if constexpr (std::is_same_v<T, ExpectedResult>) {
result = std::forward<V>(value);
} else {
result.emplace(std::forward<V>(value));
}
Expand All @@ -76,9 +76,9 @@ struct CoroPromise : public CoroPromiseBase {
};
template <>
struct CoroPromise<void> : public CoroPromiseBase {
using ExpectedT = Expected<>;
using ExpectedResult = Expected<>;

ExpectedT result{std::in_place};
ExpectedResult result{std::in_place};

constexpr CoroPromise() noexcept = default;

Expand Down
1 change: 0 additions & 1 deletion src/ll/api/coro/CoroTask.cpp

This file was deleted.

22 changes: 15 additions & 7 deletions src/ll/api/coro/CoroTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class CoroTask {
using promise_type = CoroPromise<T>;
using Handle = std::coroutine_handle<promise_type>;

using ExpectedT = typename CoroPromise<T>::ExpectedT;
using Result = T;

using ExpectedResult = typename CoroPromise<T>::ExpectedResult;

friend promise_type;

Expand All @@ -28,13 +30,13 @@ class CoroTask {
public:
struct ExpectedAwaiter : public WaiterBase {
constexpr ExpectedAwaiter(Handle h) : WaiterBase(h) {}
constexpr ExpectedT await_resume() noexcept { return WaiterBase::getResult(); };
constexpr ExpectedResult await_resume() noexcept { return WaiterBase::getResult(); };
};

struct ValueAwaiter : public WaiterBase {
constexpr ValueAwaiter(Handle h) : WaiterBase(h) {}
constexpr T await_resume() {
if constexpr (std::is_same_v<T, ExpectedT>) {
if constexpr (std::is_same_v<T, ExpectedResult>) {
return WaiterBase::getResult();
} else {
return WaiterBase::getResult().value();
Expand Down Expand Up @@ -65,7 +67,7 @@ class CoroTask {

template <class F>
void launch(NonNullExecutorRef executor, F&& callback)
requires(std::is_invocable_v<F, ExpectedT>)
requires(std::is_invocable_v<F, ExpectedResult>)
{
setExecutor(executor);
struct Launcher {
Expand All @@ -85,11 +87,11 @@ class CoroTask {
void launch(NonNullExecutorRef executor) {
launch(executor, [](auto&&) {});
}
ExpectedT syncLaunch(NonNullExecutorRef executor) noexcept {
ExpectedT value;
ExpectedResult syncLaunch(NonNullExecutorRef executor) noexcept {
ExpectedResult value;
try {
std::binary_semaphore cond{0};
launch(executor, [&](ExpectedT&& result) {
launch(executor, [&](ExpectedResult&& result) {
value = std::move(result);
cond.release();
});
Expand Down Expand Up @@ -118,4 +120,10 @@ inline auto collectAll(CoroTask<Ts>... tasks)
{
return CollectAllTupleAwaiter<CoroTask, Ts...>(std::move(tasks)...);
}
template <class F, class... Args>
requires(traits::is_specialization_of_v<std::invoke_result_t<F, Args...>, CoroTask>)
auto keepThis(F&& f, Args&&... args) noexcept -> std::invoke_result_t<F, Args...> {
co_return co_await std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

} // namespace ll::coro
6 changes: 3 additions & 3 deletions src/ll/api/coro/CoroTaskWaiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ template <typename T>
struct CoroTaskWaiter {
using Handle = std::coroutine_handle<CoroPromise<T>>;

using ExpectedT = typename CoroPromise<T>::ExpectedT;
using ExpectedResult = typename CoroPromise<T>::ExpectedResult;

Handle handle;

Expand Down Expand Up @@ -38,8 +38,8 @@ struct CoroTaskWaiter {
promise.exec->execute(handle);
}

constexpr ExpectedT getResult() noexcept {
ExpectedT ret = std::move(handle.promise().result);
constexpr ExpectedResult getResult() noexcept {
ExpectedResult ret = std::move(handle.promise().result);
std::exchange(handle, nullptr).destroy();
return ret;
}
Expand Down
1 change: 1 addition & 0 deletions src/ll/api/coro/Executor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "ll/api/coro/Executor.h"
#include "ll/api/coro/CoroTask.h"

namespace ll::coro {

Expand Down

0 comments on commit bb0b0bd

Please sign in to comment.