Skip to content

Commit

Permalink
Merge pull request #35 from owent/dev
Browse files Browse the repository at this point in the history
Allow custom `promise_error_transform` for C++20 coroutine.
  • Loading branch information
owent authored Sep 21, 2022
2 parents fefb1b8 + 309cdca commit 56ac7a2
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 183 deletions.
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

0 comments on commit 56ac7a2

Please sign in to comment.