Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom promise_error_transform for C++20 coroutine. #35

Merged
merged 3 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 2.1.0

1. Allow custom `promise_error_transform` for C++20 coroutine.

## 2.0.2

1. Add benchmark for `task_future`
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ enable_testing()

project(
libcopp
VERSION "2.0.2"
VERSION "2.1.0"
DESCRIPTION "Cross-platform coroutine library in C++ ."
HOMEPAGE_URL "https://libcopp.atframe.work"
LANGUAGES C CXX ASM)
Expand Down
2 changes: 1 addition & 1 deletion atframework/cmake-toolset
38 changes: 22 additions & 16 deletions include/libcopp/coroutine/callable_promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ LIBCOPP_COPP_NAMESPACE_BEGIN
template <class TFUTURE>
class LIBCOPP_COPP_API_HEAD_ONLY some_delegate;

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY callable_future;

template <class TVALUE, bool RETURN_VOID>
class LIBCOPP_COPP_API_HEAD_ONLY callable_promise_base;

template <class TPROMISE, bool RETURN_VOID>
template <class TPROMISE, class TERROR_TRANSFORM, bool RETURN_VOID>
class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable;

template <class TVALUE>
Expand Down Expand Up @@ -194,8 +194,9 @@ class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable_base : public awaitable_base
handle_type callee_;
};

template <class TPROMISE>
class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, true> : public callable_awaitable_base<TPROMISE> {
template <class TPROMISE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, TERROR_TRANSFORM, true>
: public callable_awaitable_base<TPROMISE> {
public:
using base_type = callable_awaitable_base<TPROMISE>;
using promise_type = typename base_type::promise_type;
Expand All @@ -217,8 +218,9 @@ class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, true> : public cal
}
};

template <class TPROMISE>
class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, false> : public callable_awaitable_base<TPROMISE> {
template <class TPROMISE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, TERROR_TRANSFORM, false>
: public callable_awaitable_base<TPROMISE> {
public:
using base_type = callable_awaitable_base<TPROMISE>;
using promise_type = typename base_type::promise_type;
Expand All @@ -240,18 +242,19 @@ class LIBCOPP_COPP_API_HEAD_ONLY callable_awaitable<TPROMISE, false> : public ca
callee_promise.resume_waiting(get_callee(), true);

if (!callee_promise.check_flag(promise_flag::kHasReturned)) {
return promise_error_transform<value_type>()(callee_promise.get_status());
return TERROR_TRANSFORM()(callee_promise.get_status());
}

return std::move(callee_promise.data());
}
};

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
class LIBCOPP_COPP_API_HEAD_ONLY callable_future {
public:
using value_type = TVALUE;
using self_type = callable_future<value_type>;
using error_transform = TERROR_TRANSFORM;
using self_type = callable_future<value_type, error_transform>;
class promise_type
: public callable_promise_base<value_type, std::is_void<typename std::decay<value_type>::type>::value> {
public:
Expand Down Expand Up @@ -295,7 +298,8 @@ class LIBCOPP_COPP_API_HEAD_ONLY callable_future {
# endif
};
using handle_type = LIBCOPP_MACRO_STD_COROUTINE_NAMESPACE coroutine_handle<promise_type>;
using awaitable_type = callable_awaitable<promise_type, std::is_void<typename std::decay<value_type>::type>::value>;
using awaitable_type =
callable_awaitable<promise_type, error_transform, std::is_void<typename std::decay<value_type>::type>::value>;

public:
callable_future(handle_type handle) noexcept : current_handle_{handle} {}
Expand Down Expand Up @@ -648,9 +652,9 @@ class LIBCOPP_COPP_API_HEAD_ONLY some_delegate_base {
};

// some
template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_callable_action {
using future_type = callable_future<TVALUE>;
using future_type = callable_future<TVALUE, TERROR_TRANSFORM>;
using context_type = some_delegate_context<future_type>;

inline static void suspend_future(const promise_caller_manager::handle_delegate& caller, future_type& callee) {
Expand All @@ -668,11 +672,13 @@ struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_callable_action {
}
};

template <class TVALUE>
class LIBCOPP_COPP_API_HEAD_ONLY some_delegate<callable_future<TVALUE>>
: public some_delegate_base<callable_future<TVALUE>, some_delegate_callable_action<TVALUE>> {
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY some_delegate<callable_future<TVALUE, TERROR_TRANSFORM>>
: public some_delegate_base<callable_future<TVALUE, TERROR_TRANSFORM>,
some_delegate_callable_action<TVALUE, TERROR_TRANSFORM>> {
public:
using base_type = some_delegate_base<callable_future<TVALUE>, some_delegate_callable_action<TVALUE>>;
using base_type = some_delegate_base<callable_future<TVALUE, TERROR_TRANSFORM>,
some_delegate_callable_action<TVALUE, TERROR_TRANSFORM>>;
using future_type = typename base_type::future_type;
using value_type = typename base_type::value_type;
using ready_output_type = typename base_type::ready_output_type;
Expand Down
58 changes: 34 additions & 24 deletions include/libcopp/coroutine/generator_promise.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ LIBCOPP_COPP_NAMESPACE_BEGIN
template <class TVALUE>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_base;

template <class TVALUE, bool RETURN_VOID>
template <class TVALUE, class TERROR_TRANSFORM, bool RETURN_VOID>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate;

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context;

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY generator_future;

template <class TPROMISE, bool RETURN_VOID>
Expand Down Expand Up @@ -101,8 +101,9 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_context_base {
promise_caller_manager caller_manager_;
};

template <class TVALUE>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, true> : public generator_context_base<TVALUE> {
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, TERROR_TRANSFORM, true>
: public generator_context_base<TVALUE> {
public:
using base_type = generator_context_base<TVALUE>;
using value_type = typename base_type::value_type;
Expand Down Expand Up @@ -145,8 +146,9 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, true> : publ
using base_type::wake;
};

template <class TVALUE>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, false> : public generator_context_base<TVALUE> {
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, TERROR_TRANSFORM, false>
: public generator_context_base<TVALUE> {
public:
using base_type = generator_context_base<TVALUE>;
using value_type = typename base_type::value_type;
Expand All @@ -163,7 +165,7 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, false> : pub

~generator_context_delegate() {
if (is_pending()) {
set_value(promise_error_transform<value_type>()(promise_status::kKilled));
set_value(TERROR_TRANSFORM()(promise_status::kKilled));
} else {
wake();
}
Expand Down Expand Up @@ -212,13 +214,16 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_context_delegate<TVALUE, false> : pub
using base_type::wake;
};

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY generator_context
: public generator_context_delegate<TVALUE, std::is_void<typename std::decay<TVALUE>::type>::value>,
public std::enable_shared_from_this<generator_context<TVALUE>> {
: public generator_context_delegate<TVALUE, TERROR_TRANSFORM,
std::is_void<typename std::decay<TVALUE>::type>::value>,
public std::enable_shared_from_this<generator_context<TVALUE, TERROR_TRANSFORM>> {
public:
using base_type = generator_context_delegate<TVALUE, std::is_void<typename std::decay<TVALUE>::type>::value>;
using base_type =
generator_context_delegate<TVALUE, TERROR_TRANSFORM, std::is_void<typename std::decay<TVALUE>::type>::value>;
using value_type = typename base_type::value_type;
using error_transform = TERROR_TRANSFORM;

public:
template <class... TARGS>
Expand Down Expand Up @@ -398,6 +403,7 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, true> : public ge
using vtable_type = typename base_type::vtable_type;
using await_suspend_callback_type = typename base_type::await_suspend_callback_type;
using await_resume_callback_type = typename base_type::await_resume_callback_type;
using error_transform = typename context_type::error_transform;

public:
using base_type::await_ready;
Expand All @@ -424,6 +430,7 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, false> : public g
using vtable_type = typename base_type::vtable_type;
using await_suspend_callback_type = typename base_type::await_suspend_callback_type;
using await_resume_callback_type = typename base_type::await_resume_callback_type;
using error_transform = typename context_type::error_transform;

public:
using base_type::await_ready;
Expand All @@ -443,7 +450,7 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, false> : public g
promise_status result_status = detach();

if (promise_status::kDone != result_status) {
return promise_error_transform<value_type>()(result_status);
return error_transform()(result_status);
}

COPP_LIKELY_IF (nullptr != get_context()) {
Expand All @@ -453,7 +460,7 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, false> : public g
return multiple_callers_constructor<value_type>::return_value(*get_context()->data());
}
} else {
return promise_error_transform<value_type>()(promise_status::kInvalid);
return error_transform()(promise_status::kInvalid);
}
}

Expand All @@ -462,12 +469,13 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_awaitable<TCONTEXT, false> : public g
using base_type::get_context;
};

template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM = promise_error_transform<TVALUE>>
class LIBCOPP_COPP_API_HEAD_ONLY generator_future {
public:
using value_type = TVALUE;
using self_type = generator_future<value_type>;
using context_type = generator_context<value_type>;
using error_transform = TERROR_TRANSFORM;
using self_type = generator_future<value_type, error_transform>;
using context_type = generator_context<value_type, error_transform>;
using context_pointer_type = std::shared_ptr<context_type>;
using awaitable_type = generator_awaitable<context_type, std::is_void<typename std::decay<value_type>::type>::value>;
using vtable_type = typename awaitable_type::vtable_type;
Expand Down Expand Up @@ -538,17 +546,17 @@ class LIBCOPP_COPP_API_HEAD_ONLY generator_future {
template <class TFUTURE>
friend class LIBCOPP_COPP_API_HEAD_ONLY some_delegate;

template <class TFUTURE>
template <class TFUTURE, class>
friend struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_generator_action;

std::shared_ptr<context_type> context_;
copp::util::intrusive_ptr<vtable_type> vtable_;
};

// some
template <class TVALUE>
template <class TVALUE, class TERROR_TRANSFORM>
struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_generator_action {
using future_type = generator_future<TVALUE>;
using future_type = generator_future<TVALUE, TERROR_TRANSFORM>;
using context_type = some_delegate_context<future_type>;

inline static void suspend_future(const promise_caller_manager::handle_delegate& caller, future_type& generator) {
Expand All @@ -572,11 +580,13 @@ struct LIBCOPP_COPP_API_HEAD_ONLY some_delegate_generator_action {
inline static bool is_pending(future_type& future_object) noexcept { return future_object.is_pending(); }
};

template <class TVALUE>
class LIBCOPP_COPP_API_HEAD_ONLY some_delegate<generator_future<TVALUE>>
: public some_delegate_base<generator_future<TVALUE>, some_delegate_generator_action<TVALUE>> {
template <class TVALUE, class TERROR_TRANSFORM>
class LIBCOPP_COPP_API_HEAD_ONLY some_delegate<generator_future<TVALUE, TERROR_TRANSFORM>>
: public some_delegate_base<generator_future<TVALUE, TERROR_TRANSFORM>,
some_delegate_generator_action<TVALUE, TERROR_TRANSFORM>> {
public:
using base_type = some_delegate_base<generator_future<TVALUE>, some_delegate_generator_action<TVALUE>>;
using base_type = some_delegate_base<generator_future<TVALUE, TERROR_TRANSFORM>,
some_delegate_generator_action<TVALUE, TERROR_TRANSFORM>>;
using future_type = typename base_type::future_type;
using value_type = typename base_type::value_type;
using ready_output_type = typename base_type::ready_output_type;
Expand Down
12 changes: 6 additions & 6 deletions include/libcotask/task_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ struct LIBCOPP_COTASK_API_HEAD_ONLY task_manager_node<task<TCO_MACRO>> {
};

#if defined(LIBCOPP_MACRO_ENABLE_STD_COROUTINE) && LIBCOPP_MACRO_ENABLE_STD_COROUTINE
template <class TVALUE, class TPRIVATE_DATA>
struct LIBCOPP_COTASK_API_HEAD_ONLY task_manager_node<task_future<TVALUE, TPRIVATE_DATA>> {
using task_type = task_future<TVALUE, TPRIVATE_DATA>;
template <class TVALUE, class TPRIVATE_DATA, class TERROR_TRANSFORM>
struct LIBCOPP_COTASK_API_HEAD_ONLY task_manager_node<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;

task_type task_;
typename std::set<task_timer_node<typename task_type::id_type>>::iterator timer_node;
Expand Down Expand Up @@ -860,10 +860,10 @@ class LIBCOPP_COTASK_API_HEAD_ONLY task_manager<task<TCO_MACRO>> {
/**
* @brief task manager for C++20 coroutine task
*/
template <class TVALUE, class TPRIVATE_DATA>
class LIBCOPP_COTASK_API_HEAD_ONLY task_manager<task_future<TVALUE, TPRIVATE_DATA>> {
template <class TVALUE, class TPRIVATE_DATA, class TERROR_TRANSFORM>
class LIBCOPP_COTASK_API_HEAD_ONLY task_manager<task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>> {
public:
using task_type = task_future<TVALUE, TPRIVATE_DATA>;
using task_type = task_future<TVALUE, TPRIVATE_DATA, TERROR_TRANSFORM>;
using container_type = std::unordered_map<typename task_type::id_type, detail::task_manager_node<task_type>>;
using id_type = typename task_type::id_type;
using task_status_type = typename task_type::task_status_type;
Expand Down
Loading