feat support Async

This commit is contained in:
tqcq 2024-04-19 00:38:35 +08:00
parent 5d07e41460
commit 07b790557b
4 changed files with 61 additions and 3 deletions

View File

@ -1,5 +1,6 @@
#include "sled/futures/future.h" #include "sled/futures/future.h"
#include "sled/system/thread_pool.h"
namespace sled { namespace sled {
namespace future_detail { namespace future_detail {
@ -12,4 +13,24 @@ DecrementFuturesUsage()
{} {}
}// namespace future_detail }// namespace future_detail
static ThreadPool g_default_thread_pool;
TaskQueueBase *g_default_scheduler = &g_default_thread_pool;
void
SetDefaultScheduler(TaskQueueBase *scheduler) noexcept
{
if (scheduler == nullptr) {
g_default_scheduler = &g_default_thread_pool;
} else {
g_default_scheduler = scheduler;
}
}
TaskQueueBase *
GetDefaultScheduler() noexcept
{
return g_default_scheduler;
}
}// namespace sled }// namespace sled

View File

@ -56,9 +56,10 @@ struct FutureData {
}; };
}// namespace future_detail }// namespace future_detail
// void SetDefaultScheduler(TaskQueueBase *scheduler) noexcept;
TaskQueueBase *GetDefaultScheduler() noexcept;
template<typename T, typename FailureT> template<typename T, typename FailureT = std::exception>
class Future { class Future {
static_assert(!std::is_same<T, void>::value, "Future<void, _> is not allowed. Use Future<bool, _> instead"); static_assert(!std::is_same<T, void>::value, "Future<void, _> is not allowed. Use Future<bool, _> instead");
static_assert(!std::is_same<FailureT, void>::value, "Future<_, void> is not allowed. Use Future<_, bool> instead"); static_assert(!std::is_same<FailureT, void>::value, "Future<_, void> is not allowed. Use Future<_, bool> instead");
@ -329,6 +330,27 @@ public:
return result; return result;
} }
template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>>
static Future<T, FailureT> Async(Func &&f) noexcept
{
Future<T, FailureT> result = Future<T, FailureT>::Create();
sled::GetDefaultScheduler()->PostTask([result, f]() mutable noexcept {
try {
result.FillSuccess(f());
} catch (const std::exception &e) {
result.FillFailure(future_detail::ExceptionFailure<FailureT>(e));
} catch (...) {
result.FillFailure(future_detail::ExceptionFailure<FailureT>());
}
});
return result;
}
static Future<T, FailureT> AsyncWithValue(const T &value) noexcept
{
return Async([value]() { return value; });
}
static Future<typename std::decay<T>::type, FailureT> Successful(T &&value) noexcept static Future<typename std::decay<T>::type, FailureT> Successful(T &&value) noexcept
{ {
Future<typename std::decay<T>::type, FailureT> result Future<typename std::decay<T>::type, FailureT> result
@ -437,6 +459,7 @@ private:
std::shared_ptr<future_detail::FutureData<T, FailureT>> data_; std::shared_ptr<future_detail::FutureData<T, FailureT>> data_;
}; };
}// namespace sled }// namespace sled
#endif// SLED_FUTURES_FUTURE_H #endif// SLED_FUTURES_FUTURE_H

View File

@ -102,4 +102,18 @@ TEST_SUITE("future")
CHECK_EQ(tid, f.Result()); CHECK_EQ(tid, f.Result());
CHECK_NE(self_tid, f.Result()); CHECK_NE(self_tid, f.Result());
} }
TEST_CASE("Async")
{
auto f = sled::Future<int>::Async([]() { return 42; });
CHECK_EQ(f.Result(), 42);
auto f2 = sled::Future<int>::Async([]() {
throw std::runtime_error("test");
return 1;
});
CHECK_FALSE(f2.IsFailed());
auto f3 = sled::Future<std::string>::AsyncWithValue("11");
CHECK_EQ(f3.Result(), "11");
}
} }

View File

@ -10,7 +10,7 @@ namespace sled {
template<typename T, typename FailureT> template<typename T, typename FailureT>
class Future; class Future;
template<typename T, typename FailureT> template<typename T, typename FailureT = std::exception>
class Promise { class Promise {
static_assert(!std::is_same<T, void>::value, "Promise<void, _> is not allowed. Use Promise<bool, _> instead"); static_assert(!std::is_same<T, void>::value, "Promise<void, _> is not allowed. Use Promise<bool, _> instead");
static_assert(!std::is_same<FailureT, void>::value, static_assert(!std::is_same<FailureT, void>::value,