# diagrams that involve STL classes more complete and accurate. | # diagrams that involve STL classes more complete and accurate. | ||||
# The default value is: NO. | # The default value is: NO. | ||||
BUILTIN_STL_SUPPORT = NO | |||||
BUILTIN_STL_SUPPORT = YES | |||||
# If you use Microsoft's C++/CLI language, you should set this option to YES to | # If you use Microsoft's C++/CLI language, you should set this option to YES to | ||||
# enable parsing support. | # enable parsing support. | ||||
# included in the documentation. | # included in the documentation. | ||||
# The default value is: NO. | # The default value is: NO. | ||||
EXTRACT_STATIC = NO | |||||
EXTRACT_STATIC = YES | |||||
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined | # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined | ||||
# locally in source files will be included in the documentation. If set to NO, | # locally in source files will be included in the documentation. If set to NO, | ||||
# documentation. | # documentation. | ||||
# The default value is: NO. | # The default value is: NO. | ||||
HIDE_FRIEND_COMPOUNDS = NO | |||||
HIDE_FRIEND_COMPOUNDS = YES | |||||
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any | # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any | ||||
# documentation blocks found inside the body of a function. If set to NO, these | # documentation blocks found inside the body of a function. If set to NO, these | ||||
# the files that are included by a file in the documentation of that file. | # the files that are included by a file in the documentation of that file. | ||||
# The default value is: YES. | # The default value is: YES. | ||||
SHOW_INCLUDE_FILES = YES | |||||
SHOW_INCLUDE_FILES = NO | |||||
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each | # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each | ||||
# grouped member an include statement to the documentation, telling the reader | # grouped member an include statement to the documentation, telling the reader | ||||
# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, | # C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, | ||||
# *.vhdl, *.ucf, *.qsf and *.ice. | # *.vhdl, *.ucf, *.qsf and *.ice. | ||||
FILE_PATTERNS = *.c \ | |||||
*.cc \ | |||||
*.cxx \ | |||||
*.cpp \ | |||||
*.c++ \ | |||||
*.java \ | |||||
*.ii \ | |||||
*.ixx \ | |||||
*.ipp \ | |||||
*.i++ \ | |||||
FILE_PATTERNS = *.java \ | |||||
*.idl \ | *.idl \ | ||||
*.ddl \ | *.ddl \ | ||||
*.odl \ | *.odl \ | ||||
*.h \ | *.h \ | ||||
*.hh \ | |||||
*.hxx \ | |||||
*.hpp \ | |||||
*.h++ \ | |||||
*.cs \ | *.cs \ | ||||
*.d \ | *.d \ | ||||
*.php \ | *.php \ | ||||
# Note that relative paths are relative to the directory from which doxygen is | # Note that relative paths are relative to the directory from which doxygen is | ||||
# run. | # run. | ||||
EXCLUDE = | |||||
EXCLUDE = channel_v1.h \ | |||||
event_v1.h \ | |||||
mutex_v1.h | |||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or | # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or | ||||
# directories that are symbolic links (a Unix file system feature) are excluded | # directories that are symbolic links (a Unix file system feature) are excluded |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
namespace detail | namespace detail | ||||
}; | }; | ||||
} | } | ||||
} | } | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template<class _Ty> | template<class _Ty> | ||||
struct awaitable_impl_t | struct awaitable_impl_t | ||||
{ | { | ||||
} | } | ||||
}; | }; | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
template<class _Ty> | template<class _Ty> | ||||
struct [[nodiscard]] awaitable_t<_Ty&> : public awaitable_impl_t<_Ty&> | struct [[nodiscard]] awaitable_t<_Ty&> : public awaitable_impl_t<_Ty&> | ||||
{ | { | ||||
this->_state = nullptr; | this->_state = nullptr; | ||||
} | } | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
} | } |
inline namespace channel_v2 | inline namespace channel_v2 | ||||
{ | { | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
/** | /** | ||||
* @brief 可传递数据的模板信号量。 | * @brief 可传递数据的模板信号量。 | ||||
template<class U | template<class U | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
COMMA_RESUMEF_ENABLE_IF(std::is_constructible_v<value_type, U&&>) | COMMA_RESUMEF_ENABLE_IF(std::is_constructible_v<value_type, U&&>) | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
RESUMEF_REQUIRES(std::is_constructible_v<_Ty, U&&>) | RESUMEF_REQUIRES(std::is_constructible_v<_Ty, U&&>) | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
write_awaiter operator << (U&& val) const noexcept(std::is_move_constructible_v<U>); | write_awaiter operator << (U&& val) const noexcept(std::is_move_constructible_v<U>); | ||||
/** | /** | ||||
template<class U | template<class U | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
COMMA_RESUMEF_ENABLE_IF(std::is_constructible_v<value_type, U&&>) | COMMA_RESUMEF_ENABLE_IF(std::is_constructible_v<value_type, U&&>) | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
RESUMEF_REQUIRES(std::is_constructible_v<_Ty, U&&>) | RESUMEF_REQUIRES(std::is_constructible_v<_Ty, U&&>) | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
write_awaiter write(U&& val) const noexcept(std::is_move_constructible_v<U>); | write_awaiter write(U&& val) const noexcept(std::is_move_constructible_v<U>); | ||||
channel_t& operator = (channel_t&&) = default; | channel_t& operator = (channel_t&&) = default; | ||||
private: | private: | ||||
std::shared_ptr<channel_type> _chan; | std::shared_ptr<channel_type> _chan; | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
}; | }; | ||||
struct channel_t<void, _Option, _OptimizationThread> | struct channel_t<void, _Option, _OptimizationThread> | ||||
{ | { | ||||
}; | }; | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
/** | /** | ||||
* @brief 利用channel_t重定义的信号量。 | * @brief 利用channel_t重定义的信号量。 |
| |||||
#pragma once | |||||
#pragma once | |||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template <typename T> | template <typename T> | ||||
struct counted_ptr | struct counted_ptr | ||||
{ | { |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
struct get_current_scheduler_awaitor | struct get_current_scheduler_awaitor | ||||
{ | { | ||||
bool await_ready() const noexcept | bool await_ready() const noexcept |
#define RESUMEF_NS namespace resumef | #define RESUMEF_NS namespace resumef | ||||
#endif | #endif | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
struct scheduler_t; | struct scheduler_t; | ||||
template<class _Ty = void> | template<class _Ty = void> | ||||
struct awaitable_t; | struct awaitable_t; | ||||
//获得当前线程下的调度器 | |||||
scheduler_t* this_scheduler(); | |||||
struct state_base_t; | |||||
struct switch_scheduler_t; | |||||
#else //DOXYGEN_SKIP_PROPERTY | |||||
namespace resumef { | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template<typename _PromiseT = void> | template<typename _PromiseT = void> | ||||
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; | using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; | ||||
using suspend_always = std::experimental::suspend_always; | using suspend_always = std::experimental::suspend_always; | ||||
using suspend_never = std::experimental::suspend_never; | using suspend_never = std::experimental::suspend_never; | ||||
struct state_base_t; | |||||
struct switch_scheduler_t; | |||||
template<class... _Mutexes> | template<class... _Mutexes> | ||||
using scoped_lock = std::scoped_lock<_Mutexes...>; | using scoped_lock = std::scoped_lock<_Mutexes...>; | ||||
constexpr size_t _Version = LIB_RESUMEF_VERSION; | constexpr size_t _Version = LIB_RESUMEF_VERSION; | ||||
//获得当前线程下的调度器 | |||||
scheduler_t* this_scheduler(); | |||||
} | } | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
#if RESUMEF_DEBUG_COUNTER | #if RESUMEF_DEBUG_COUNTER | ||||
extern std::mutex g_resumef_cout_mutex; | extern std::mutex g_resumef_cout_mutex; | ||||
extern std::atomic<intptr_t> g_resumef_state_count; | extern std::atomic<intptr_t> g_resumef_state_count; | ||||
} | } | ||||
#include "exception.inl" | #include "exception.inl" | ||||
#endif //DOXYGEN_SKIP_PROPERTY |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
namespace detail | namespace detail | ||||
inline namespace event_v2 | inline namespace event_v2 | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
struct event_t | struct event_t | ||||
{ | { | ||||
using event_impl_ptr = std::shared_ptr<detail::event_v2_impl>; | using event_impl_ptr = std::shared_ptr<detail::event_v2_impl>; |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
enum struct error_code | enum struct error_code | ||||
{ | { | ||||
none, | none, |
| | ||||
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template<class _Ty> | template<class _Ty> | ||||
struct [[nodiscard]] future_t | struct [[nodiscard]] future_t | ||||
{ | { | ||||
}; | }; | ||||
} | } | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
namespace std { | namespace std { | ||||
namespace experimental { | namespace experimental { | ||||
}; | }; | ||||
} | } | ||||
} // namespace std::experimental | } // namespace std::experimental | ||||
#endif //DOXYGEN_SKIP_PROPERTY |
#pragma push_macro("new") | #pragma push_macro("new") | ||||
#undef new | #undef new | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template <typename _Ty, typename promise_type> | template <typename _Ty, typename promise_type> | ||||
struct generator_iterator; | struct generator_iterator; | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
template<typename promise_type> | template<typename promise_type> | ||||
struct generator_iterator<void, promise_type> | struct generator_iterator<void, promise_type> | ||||
{ | { | ||||
return this->_Coro.promise()._CurrentValue; | return this->_Coro.promise()._CurrentValue; | ||||
} | } | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template <typename _Ty, typename _Alloc> | template <typename _Ty, typename _Alloc> | ||||
struct generator_t | struct generator_t | ||||
using value_type = _Ty; | using value_type = _Ty; | ||||
using state_type = state_generator_t; | using state_type = state_generator_t; | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
struct promise_type | struct promise_type | ||||
{ | { | ||||
using value_type = _Ty; | using value_type = _Ty; | ||||
counted_ptr<state_type> _state = state_generator_t::_Alloc_state(); | counted_ptr<state_type> _state = state_generator_t::_Alloc_state(); | ||||
#endif | #endif | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
typedef generator_iterator<_Ty, promise_type> iterator; | typedef generator_iterator<_Ty, promise_type> iterator; | ||||
#pragma pop_macro("new") | #pragma pop_macro("new") | ||||
#pragma pack(pop) | #pragma pack(pop) | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
namespace std { | namespace std { | ||||
namespace experimental { | namespace experimental { | ||||
}; | }; | ||||
} | } | ||||
} // namespace std::experimental | } // namespace std::experimental | ||||
#endif //DOXYGEN_SKIP_PROPERTY |
inline namespace mutex_v2 | inline namespace mutex_v2 | ||||
{ | { | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
/** | /** | ||||
* @brief 提示手工解锁,故相关的lock()函数不再返回scoped_unlock_t。 | * @brief 提示手工解锁,故相关的lock()函数不再返回scoped_unlock_t。 | ||||
*/ | */ | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); | static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static future_t<> lock(adopt_manual_unlock_t manual_unlock_tag, _Mtxs&... mtxs); | static future_t<> lock(adopt_manual_unlock_t manual_unlock_tag, _Mtxs&... mtxs); | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static future_t<> unlock(_Mtxs&... mtxs); | static future_t<> unlock(_Mtxs&... mtxs); | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static scoped_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); | static scoped_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static void lock(adopt_manual_unlock_t manual_unlock_tag, void* unique_address, _Mtxs&... mtxs); | static void lock(adopt_manual_unlock_t manual_unlock_tag, void* unique_address, _Mtxs&... mtxs); | ||||
template<class... _Mtxs | template<class... _Mtxs | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | #ifndef DOXYGEN_SKIP_PROPERTY | ||||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | , typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
> | > | ||||
static void unlock(void* unique_address, _Mtxs&... mtxs); | static void unlock(void* unique_address, _Mtxs&... mtxs); | ||||
template<class... _Mtxs> friend struct scoped_unlock_t; | template<class... _Mtxs> friend struct scoped_unlock_t; | ||||
mutex_impl_ptr _mutex; | mutex_impl_ptr _mutex; | ||||
#endif | |||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
}; | }; | ||||
} | } | ||||
} | } |
#pragma push_macro("new") | #pragma push_macro("new") | ||||
#undef new | #undef new | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
struct suspend_on_initial; | struct suspend_on_initial; | ||||
void return_void(); //co_return; | void return_void(); //co_return; | ||||
suspend_always yield_value(); | suspend_always yield_value(); | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
} | } | ||||
#pragma pop_macro("new") | #pragma pop_macro("new") |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
struct task_base_t; | |||||
/** | |||||
* @brief 协程任务的基类。 | |||||
*/ | |||||
struct task_base_t | struct task_base_t | ||||
{ | { | ||||
task_base_t() = default; | task_base_t() = default; | ||||
virtual ~task_base_t(); | virtual ~task_base_t(); | ||||
state_base_t* get_state() const noexcept | |||||
{ | |||||
return _state.get(); | |||||
} | |||||
protected: | protected: | ||||
friend scheduler_t; | |||||
counted_ptr<state_base_t> _state; | counted_ptr<state_base_t> _state; | ||||
}; | }; | ||||
#endif | |||||
//---------------------------------------------------------------------------------------------- | //---------------------------------------------------------------------------------------------- | ||||
/** | |||||
* @brief 协程任务类。 | |||||
* @details 每启动一个新的协程,则对应一个协程任务类。\n | |||||
* 一方面,task_t<>用于标记协程是否执行完毕;\n | |||||
* 另一方面,对于通过函数对象(functor/lambda)启动的协程,有很大概率,此协程的内部变量,依赖此函数对象的生存期。\n | |||||
* tast_t<>的针对函数对象的特化版本,会持有此函数对象的拷贝,从而保证协程内部变量的生存期。从而减少外部使用协程函数对象的工作量。\n | |||||
* 如果不希望task_t<>持有此函数对象,则通过调用此函数对象来启动协程,即:\n | |||||
* go functor; \n | |||||
* 替换为\n | |||||
* go functor(); | |||||
*/ | |||||
template<class _Ty, class = std::void_t<>> | template<class _Ty, class = std::void_t<>> | ||||
struct task_t; | struct task_t; | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
template<class _Ty> | template<class _Ty> | ||||
struct task_t<_Ty, std::void_t<traits::is_future<std::remove_reference_t<_Ty>>>> : public task_base_t | struct task_t<_Ty, std::void_t<traits::is_future<std::remove_reference_t<_Ty>>>> : public task_base_t | ||||
{ | { | ||||
this->initialize(f); | this->initialize(f); | ||||
} | } | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
} | } |
void scheduler_t::new_task(task_base_t * task) | void scheduler_t::new_task(task_base_t * task) | ||||
{ | { | ||||
state_base_t* sptr = task->get_state(); | |||||
state_base_t* sptr = task->_state.get(); | |||||
sptr->set_scheduler(this); | sptr->set_scheduler(this); | ||||
{ | { | ||||
void scheduler_t::add_switch(std::unique_ptr<task_base_t> task) | void scheduler_t::add_switch(std::unique_ptr<task_base_t> task) | ||||
{ | { | ||||
state_base_t* sptr = task->get_state(); | |||||
state_base_t* sptr = task->_state.get(); | |||||
scoped_lock<spinlock> __guard(_lock_ready); | scoped_lock<spinlock> __guard(_lock_ready); | ||||
this->_ready_task.emplace(sptr, std::move(task)); | this->_ready_task.emplace(sptr, std::move(task)); |
#endif | #endif | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
namespace detail | namespace detail | ||||
{ | { | ||||
template<class _Ty, class _Cont = std::vector<_Ty>> | template<class _Ty, class _Cont = std::vector<_Ty>> | ||||
#undef LOCK_ASSEMBLE_AWAIT | #undef LOCK_ASSEMBLE_AWAIT | ||||
#undef LOCK_ASSEMBLE_RETURN | #undef LOCK_ASSEMBLE_RETURN | ||||
} | } | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
template<class _Ty, class _Cont = std::vector<_Ty>, class _Assemble = detail::_LockVectorAssembleT<_Ty, _Cont>> | template<class _Ty, class _Cont = std::vector<_Ty>, class _Assemble = detail::_LockVectorAssembleT<_Ty, _Cont>> | ||||
class scoped_lock_range { // class with destructor that unlocks mutexes | class scoped_lock_range { // class with destructor that unlocks mutexes |
#pragma once | #pragma once | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
struct state_base_t | struct state_base_t | ||||
{ | { | ||||
using _Alloc_char = std::allocator<char>; | using _Alloc_char = std::allocator<char>; | ||||
void set_exception_internal(std::exception_ptr e); | void set_exception_internal(std::exception_ptr e); | ||||
}; | }; | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
template <typename _Ty> | template <typename _Ty> | ||||
struct state_t<_Ty&> final : public state_future_t | struct state_t<_Ty&> final : public state_future_t | ||||
{ | { | ||||
private: | private: | ||||
std::exception_ptr _exception; | std::exception_ptr _exception; | ||||
}; | }; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
} | } | ||||
#pragma once | |||||
#pragma once | |||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
struct timer_manager; | struct timer_manager; | ||||
typedef std::shared_ptr<timer_manager> timer_mgr_ptr; | typedef std::shared_ptr<timer_manager> timer_mgr_ptr; | ||||
typedef std::weak_ptr<timer_manager> timer_mgr_wptr; | typedef std::weak_ptr<timer_manager> timer_mgr_wptr; | ||||
typedef std::chrono::system_clock timer_clock_type; | typedef std::chrono::system_clock timer_clock_type; | ||||
typedef std::function<void(bool)> timer_callback_type; | typedef std::function<void(bool)> timer_callback_type; | ||||
/** | |||||
* @brief 定时器对象。 | |||||
*/ | |||||
struct timer_target : public std::enable_shared_from_this<timer_target> | struct timer_target : public std::enable_shared_from_this<timer_target> | ||||
{ | { | ||||
friend timer_manager; | friend timer_manager; | ||||
timer_target & operator = (const timer_target &) = delete; | timer_target & operator = (const timer_target &) = delete; | ||||
timer_target & operator = (timer_target && right_) = delete; | timer_target & operator = (timer_target && right_) = delete; | ||||
}; | }; | ||||
typedef std::shared_ptr<timer_target> timer_target_ptr; | typedef std::shared_ptr<timer_target> timer_target_ptr; | ||||
typedef std::weak_ptr<timer_target> timer_target_wptr; | typedef std::weak_ptr<timer_target> timer_target_wptr; | ||||
} | } | ||||
/** | |||||
* @brief 定时器句柄。 | |||||
* @details 对定时器对象和定时器管理器都采用弱引用。 | |||||
*/ | |||||
struct timer_handler | struct timer_handler | ||||
{ | { | ||||
private: | private: | ||||
timer_mgr_wptr _manager; | timer_mgr_wptr _manager; | ||||
detail::timer_target_wptr _target; | detail::timer_target_wptr _target; | ||||
public: | public: | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
timer_handler() = default; | timer_handler() = default; | ||||
timer_handler(const timer_handler &) = default; | timer_handler(const timer_handler &) = default; | ||||
timer_handler(timer_handler && right_) noexcept; | timer_handler(timer_handler && right_) noexcept; | ||||
timer_handler & operator = (const timer_handler &) = default; | timer_handler & operator = (const timer_handler &) = default; | ||||
timer_handler & operator = (timer_handler && right_) noexcept; | timer_handler & operator = (timer_handler && right_) noexcept; | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
timer_handler(timer_manager * manager_, const detail::timer_target_ptr & target_); | timer_handler(timer_manager * manager_, const detail::timer_target_ptr & target_); | ||||
void reset(); | void reset(); | ||||
bool expired() const; | bool expired() const; | ||||
}; | }; | ||||
/** | |||||
* @brief 定时器管理器。 | |||||
*/ | |||||
struct timer_manager : public std::enable_shared_from_this<timer_manager> | struct timer_manager : public std::enable_shared_from_this<timer_manager> | ||||
{ | { | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
typedef detail::timer_target timer_target; | typedef detail::timer_target timer_target; | ||||
typedef detail::timer_target_ptr timer_target_ptr; | typedef detail::timer_target_ptr timer_target_ptr; | ||||
typedef detail::timer_clock_type clock_type; | typedef detail::timer_clock_type clock_type; | ||||
typedef std::vector<timer_target_ptr> timer_vector_type; | typedef std::vector<timer_target_ptr> timer_vector_type; | ||||
typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | ||||
protected: | |||||
spinlock _added_mtx; | |||||
timer_vector_type _added_timers; | |||||
#endif | |||||
public: | public: | ||||
timer_map_type _runing_timers; | |||||
timer_manager(); | timer_manager(); | ||||
~timer_manager(); | ~timer_manager(); | ||||
void clear(); | void clear(); | ||||
void update(); | void update(); | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
template<class _Cb> | template<class _Cb> | ||||
timer_target_ptr add_(const duration_type & dt_, _Cb && cb_) | timer_target_ptr add_(const duration_type & dt_, _Cb && cb_) | ||||
{ | { | ||||
return add_(std::make_shared<timer_target>(tp_, std::forward<_Cb>(cb_))); | return add_(std::make_shared<timer_target>(tp_, std::forward<_Cb>(cb_))); | ||||
} | } | ||||
private: | private: | ||||
spinlock _added_mtx; | |||||
timer_vector_type _added_timers; | |||||
timer_map_type _runing_timers; | |||||
timer_target_ptr add_(const timer_target_ptr & sptr); | timer_target_ptr add_(const timer_target_ptr & sptr); | ||||
static void call_target_(const timer_target_ptr & sptr, bool canceld); | static void call_target_(const timer_target_ptr & sptr, bool canceld); | ||||
#endif | |||||
}; | }; | ||||
//最最重要的,要统一ranged when_any的返回值,还得做一个运行时通过下标设置std::variant<>的东西 | //最最重要的,要统一ranged when_any的返回值,还得做一个运行时通过下标设置std::variant<>的东西 | ||||
//std::any除了内存布局不太理想,其他方面几乎没缺点(在此应用下) | //std::any除了内存布局不太理想,其他方面几乎没缺点(在此应用下) | ||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
RESUMEF_NS | RESUMEF_NS | ||||
{ | { | ||||
using when_any_pair = std::pair<intptr_t, any_t>; | using when_any_pair = std::pair<intptr_t, any_t>; | ||||
} | } | ||||
} | } | ||||
#endif //DOXYGEN_SKIP_PROPERTY | |||||
#ifndef DOXYGEN_SKIP_PROPERTY | |||||
inline namespace when_v2 | inline namespace when_v2 | ||||
{ | { | ||||
#else | |||||
struct when | |||||
{ | |||||
#endif | |||||
template<_WhenTaskT... _Awaitable | template<_WhenTaskT... _Awaitable | ||||
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) | COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) | ||||
> | > |