@@ -888,7 +888,8 @@ FILE_PATTERNS = *.java \ | |||
*.vhdl \ | |||
*.ucf \ | |||
*.qsf \ | |||
*.ice | |||
*.ice \ | |||
*.inl | |||
# The RECURSIVE tag can be used to specify whether or not subdirectories should | |||
# be searched for input files as well. |
@@ -6,11 +6,18 @@ | |||
namespace asio { | |||
/** | |||
* @brief 用于指示asio相关异步函数,返回resumef::future_t<>的类型,从而变成支持 librf 的协程函数。 | |||
*/ | |||
template <typename Executor = executor> | |||
struct rf_task_t | |||
{ | |||
ASIO_CONSTEXPR rf_task_t() {} | |||
}; | |||
/** | |||
* @brief 用于指示asio相关异步函数,返回resumef::future_t<>的常量,从而变成支持 librf 的协程函数。 | |||
*/ | |||
constexpr rf_task_t<> rf_task; | |||
namespace librf { |
@@ -1,8 +1,13 @@ | |||
#pragma once | |||
#pragma once | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief awaitable_t<>的公共实现部分,用于减少awaitable_t<>的重复代码。 | |||
* @param _Ty 可等待函数(awaitable function)的返回类型。 | |||
* @see 参见awaitable_t<>类的说明。 | |||
*/ | |||
template<class _Ty> | |||
struct awaitable_impl_t | |||
{ | |||
@@ -19,32 +24,67 @@ namespace resumef | |||
awaitable_impl_t& operator = (const awaitable_impl_t&) = default; | |||
awaitable_impl_t& operator = (awaitable_impl_t&&) = default; | |||
/** | |||
* @brief 发生了异常后,设置异常。 | |||
* @attention 与set_value()互斥。调用了set_exception(e)后,不能再调用set_value()。 | |||
*/ | |||
void set_exception(std::exception_ptr e) const | |||
{ | |||
this->_state->set_exception(std::move(e)); | |||
this->_state = nullptr; | |||
} | |||
/** | |||
* @brief 在协程内部,重新抛出之前设置的异常。 | |||
*/ | |||
template<class _Exp> | |||
void throw_exception(_Exp e) const | |||
{ | |||
set_exception(std::make_exception_ptr(std::move(e))); | |||
} | |||
/** | |||
* @brief 获得与之关联的future_t<>对象,作为可等待函数(awaitable function)的返回值。 | |||
*/ | |||
future_type get_future() noexcept | |||
{ | |||
return future_type{ this->_state }; | |||
} | |||
/** | |||
* @brief 管理的state_t<>对象。 | |||
*/ | |||
mutable counted_ptr<state_type> _state = state_future_t::_Alloc_state<state_type>(true); | |||
}; | |||
/** | |||
* @brief 用于包装‘异步函数’为‘可等待函数(awaitable function)’。 | |||
* @details 通过返回一个‘可等待对象(awaitor)’,符合C++ coroutines的co_await所需的接口,来达成‘可等待函数(awaitable function)’。\n | |||
* 这是扩展异步函数支持协程的重要手段。\n | |||
* \n | |||
* 典型用法是申明一个 awaitable_t<>局部变量 awaitable,\n | |||
* 在已经获得结果的情况下,直接调用 awaitable.set_value(value)设置返回值,使得可等待函数立即获得结果。\n | |||
* 在不能立即获得结果的情况下,通过在异步的回调lambda里,捕获awaitable局部变量,\n | |||
* 根据异步结果,要么调用 awaitable.set_value(value)设置结果值,要么调用 awaitable.set_exception(e)设置异常。\n | |||
* 在设置值或者异常后,调用可等待函数的协程将得以继续执行。\n | |||
* 此可等待函数通过 awaitable.get_future()返回与之关联的 future_t<>对象,作为协程的可等待对象。\n | |||
* \n | |||
* @param _Ty 可等待函数(awaitable function)的返回类型。\n | |||
* 要求至少支持移动构造和移动赋值。\n | |||
* _Ty 支持特化为 _Ty&,以及 void。 | |||
*/ | |||
template<class _Ty> | |||
struct [[nodiscard]] awaitable_t : public awaitable_impl_t<_Ty> | |||
{ | |||
using typename awaitable_impl_t<_Ty>::value_type; | |||
using awaitable_impl_t<_Ty>::awaitable_impl_t; | |||
/** | |||
* @brief 设置可等待函数的返回值。 | |||
* @details _Ty的void特化版本,则是不带参数的set_value()函数。 | |||
* @param value 返回值。必须支持通过value构造出_Ty类型。 | |||
* @attention 与set_exception()互斥。调用了set_value(value)后,不能再调用set_exception(e)。 | |||
*/ | |||
template<class U> | |||
void set_value(U&& value) const | |||
{ |
@@ -44,6 +44,7 @@ inline namespace channel_v2 | |||
/** | |||
* @brief 在协程中从channel_t里读取一个数据。 | |||
* @see 参考read()函数 | |||
* @return [co_await] value_type | |||
*/ | |||
read_awaiter operator co_await() const noexcept; | |||
@@ -2,27 +2,45 @@ | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief 专用与state的智能计数指针,通过管理state内嵌的引用计数来管理state的生存期。 | |||
*/ | |||
template <typename T> | |||
struct counted_ptr | |||
{ | |||
/** | |||
* @brief 构造一个无内容的计数指针。 | |||
*/ | |||
counted_ptr() noexcept = default; | |||
counted_ptr(const counted_ptr& cp) : _p(cp._p) | |||
/** | |||
* @brief 拷贝构造函数。 | |||
*/ | |||
counted_ptr(const counted_ptr& cp) : _p(cp._p) | |||
{ | |||
_lock(); | |||
} | |||
counted_ptr(T* p) : _p(p) | |||
/** | |||
* @brief 通过裸指针构造一个计数指针。 | |||
*/ | |||
counted_ptr(T* p) : _p(p) | |||
{ | |||
_lock(); | |||
} | |||
/** | |||
* @brief 移动构造函数。 | |||
*/ | |||
counted_ptr(counted_ptr&& cp) noexcept | |||
{ | |||
std::swap(_p, cp._p); | |||
} | |||
counted_ptr& operator=(const counted_ptr& cp) | |||
/** | |||
* @brief 拷贝赋值函数。 | |||
*/ | |||
counted_ptr& operator=(const counted_ptr& cp) | |||
{ | |||
if (&cp != this) | |||
{ | |||
@@ -32,6 +50,9 @@ namespace resumef | |||
return *this; | |||
} | |||
/** | |||
* @brief 移动赋值函数。 | |||
*/ | |||
counted_ptr& operator=(counted_ptr&& cp) noexcept | |||
{ | |||
if (&cp != this) | |||
@@ -39,21 +60,33 @@ namespace resumef | |||
return *this; | |||
} | |||
/** | |||
* @brief 析构函数中自动做一个计数减一操作。计数减为0,则删除state对象。 | |||
*/ | |||
~counted_ptr() | |||
{ | |||
_unlock(); | |||
} | |||
/** | |||
* @brief 重载指针操作符。 | |||
*/ | |||
T* operator->() const noexcept | |||
{ | |||
return _p; | |||
} | |||
/** | |||
* @brief 获得管理的state指针。 | |||
*/ | |||
T* get() const noexcept | |||
{ | |||
return _p; | |||
} | |||
/** | |||
* @brief 重置为空指针。 | |||
*/ | |||
void reset() | |||
{ | |||
_unlock(); |
@@ -26,6 +26,11 @@ namespace resumef | |||
scheduler_t* _scheduler; | |||
}; | |||
/** | |||
* @brief 获得当前协程绑定的调度器。 | |||
* @details 立即返回,没有协程切换和等待。 | |||
* @return [co_await] scheduler_t* | |||
*/ | |||
inline get_current_scheduler_awaitor get_current_scheduler() | |||
{ | |||
return {}; | |||
@@ -55,6 +60,11 @@ namespace resumef | |||
state_base_t* _state; | |||
}; | |||
/** | |||
* @brief 获得当前协程的跟state指针。 | |||
* @details 立即返回,没有协程切换和等待。 | |||
* @return [co_await] state_base_t* | |||
*/ | |||
inline get_root_state_awaitor get_root_state() | |||
{ | |||
return {}; |
@@ -1,23 +1,33 @@ | |||
#pragma once | |||
#pragma once | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief 错误ç �。 | |||
*/ | |||
enum struct error_code | |||
{ | |||
none, | |||
not_ready, // get_value called when value not available | |||
already_acquired, // attempt to get another future | |||
unlock_more, // unlock ´ÎÊý¶àÓàlock´ÎÊý | |||
read_before_write, // 0ÈÝÁ¿µÄchannel£¬ÏȶÁºóд | |||
timer_canceled, // ¶¨Ê±Æ÷±»ÒâÍâÈ¡Ïû | |||
not_await_lock, // ûÓÐÔÚгÌÖÐʹÓÃco_awaitµÈ´ýlock½á¹û | |||
not_ready, ///< get_value called when value not available | |||
already_acquired, ///< attempt to get another future | |||
unlock_more, ///< unlock 次数多余lock次数 | |||
read_before_write, ///< 0容�的channel,先读�写 | |||
timer_canceled, ///< 定时器被�外�消 | |||
not_await_lock, ///< 没有在å��程ä¸ä½¿ç”¨co_awaitç‰å¾…lock结果 | |||
max__ | |||
}; | |||
/** | |||
* @brief 通过错误ç �获得错误æ��è¿°å—符串。 | |||
*/ | |||
const char* get_error_string(error_code fe, const char* classname); | |||
/** | |||
* @brief 在�作future_t<>时产生的异常。 | |||
*/ | |||
const char* get_error_string(error_code fe, const char* classname); | |||
struct future_exception : std::logic_error | |||
{ | |||
error_code _error; | |||
@@ -28,16 +38,22 @@ namespace resumef | |||
} | |||
}; | |||
struct lock_exception : std::logic_error | |||
/** | |||
* @brief 错误使用mutex_t时产生的异常。 | |||
*/ | |||
struct mutex_exception : std::logic_error | |||
{ | |||
error_code _error; | |||
lock_exception(error_code fe) | |||
: logic_error(get_error_string(fe, "lock_exception")) | |||
mutex_exception(error_code fe) | |||
: logic_error(get_error_string(fe, "mutex_exception")) | |||
, _error(fe) | |||
{ | |||
} | |||
}; | |||
/** | |||
* @brief 错误使用channel_t时产生的异常(v2版本已ç»�ä¸�å†�抛æ¤å¼‚常了)。 | |||
*/ | |||
struct channel_exception : std::logic_error | |||
{ | |||
error_code _error; | |||
@@ -48,6 +64,9 @@ namespace resumef | |||
} | |||
}; | |||
/** | |||
* @brief 定时器���消导致的异常。 | |||
*/ | |||
struct timer_canceled_exception : public std::logic_error | |||
{ | |||
error_code _error; |
@@ -4,6 +4,12 @@ | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief 用于resumef协程的返回值。 | |||
* @details 由于coroutines的限制,协程的返回值必须明确申明,而不能通过auto推导。\n | |||
* 用在恢复函数(resumeable function)里,支持co_await和co_yield。\n | |||
* 用在可等待函数(awaitable function)里,与awaitable_t<>配套使用。 | |||
*/ | |||
template<class _Ty> | |||
struct [[nodiscard]] future_t | |||
{ |
@@ -1,4 +1,4 @@ | |||
/* | |||
/* | |||
* Modify from <experimental/generator_t.h> | |||
* Purpose: Library support of coroutines. generator_t class | |||
* http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0057r0.pdf | |||
@@ -96,6 +96,9 @@ namespace resumef | |||
}; | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
/** | |||
* @brief 专用于co_yield函数。 | |||
*/ | |||
template <typename _Ty, typename _Alloc> | |||
struct generator_t | |||
{ | |||
@@ -212,7 +215,7 @@ namespace resumef | |||
std::cout << " generator_promise::new, return ptr=" << (void*)_Rptr << std::endl; | |||
#endif | |||
//ÔÚ³õʼµØÖ·ÉϹ¹Ôìstate | |||
//在åˆ�始地å�€ä¸Šæž„é€ state | |||
{ | |||
state_type* st = state_type::_Construct(ptr); | |||
st->lock(); |
@@ -198,7 +198,7 @@ namespace resumef | |||
assert(_mutex == nullptr); | |||
if (_mutex != nullptr) | |||
{ | |||
throw lock_exception(error_code::not_await_lock); | |||
throw mutex_exception(error_code::not_await_lock); | |||
} | |||
} | |||
@@ -298,7 +298,7 @@ namespace resumef | |||
assert(_mutex == nullptr); | |||
if (_mutex != nullptr) | |||
{ | |||
throw lock_exception(error_code::not_await_lock); | |||
throw mutex_exception(error_code::not_await_lock); | |||
} | |||
} | |||
@@ -345,7 +345,7 @@ namespace resumef | |||
assert(_mutex == nullptr); | |||
if (_mutex != nullptr) | |||
{ | |||
throw lock_exception(error_code::not_await_lock); | |||
throw mutex_exception(error_code::not_await_lock); | |||
} | |||
} | |||
@@ -6,31 +6,70 @@ | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @details 不能使用操作系统提供的sleep功能,因为会阻塞协程。\n | |||
* 此函数不会阻塞线程,仅仅将当前协程挂起,直到指定时刻。\n | |||
* 其精度,取决与调度器循环的精度,以及std::chrono::system_clock的精度。简而言之,可以认为只要循环够快,精度到100ns。 | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_); | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 参考sleep_until_()函数\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
inline future_t<> sleep_for_(std::chrono::system_clock::duration dt_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_until_(std::chrono::system_clock::now() + dt_, scheduler_); | |||
} | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 参考sleep_until_()函数\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
template<class _Rep, class _Period> | |||
inline future_t<> sleep_for(std::chrono::duration<_Rep, _Period> dt_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_); | |||
} | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 参考sleep_until_()函数\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
template<class _Clock, class _Duration = typename _Clock::duration> | |||
inline future_t<> sleep_until(std::chrono::time_point<_Clock, _Duration> tp_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_); | |||
} | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 参考sleep_until_()函数\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
template<class _Rep, class _Period> | |||
inline future_t<> sleep_for(std::chrono::duration<_Rep, _Period> dt_) | |||
{ | |||
scheduler_t* sch = current_scheduler(); | |||
co_await sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *sch); | |||
} | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 参考sleep_until_()函数\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
template<class _Clock, class _Duration> | |||
inline future_t<> sleep_until(std::chrono::time_point<_Clock, _Duration> tp_) | |||
{ | |||
@@ -38,6 +77,12 @@ namespace resumef | |||
co_await sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *sch); | |||
} | |||
/** | |||
* @brief 协程专用的睡眠功能。 | |||
* @see 等同调用sleep_for(dt)\n | |||
* @return [co_await] void | |||
* @throw timer_canceled_exception 如果定时器被取消,则抛此异常。 | |||
*/ | |||
template <class Rep, class Period> | |||
inline future_t<> operator co_await(std::chrono::duration<Rep, Period> dt_) | |||
{ |
@@ -8,6 +8,9 @@ namespace resumef | |||
using spinlock = RESUMEF_USE_CUSTOM_SPINLOCK; | |||
#else | |||
/** | |||
* @brief 一个自旋锁实现。 | |||
*/ | |||
struct spinlock | |||
{ | |||
static const size_t MAX_ACTIVE_SPIN = 4000; | |||
@@ -20,11 +23,17 @@ namespace resumef | |||
std::thread::id owner_thread_id; | |||
#endif | |||
/** | |||
* @brief 初始为未加锁。 | |||
*/ | |||
spinlock() noexcept | |||
{ | |||
lck = FREE_VALUE; | |||
} | |||
/** | |||
* @brief 获得锁。会一直阻塞线程直到获得锁。 | |||
*/ | |||
void lock() noexcept | |||
{ | |||
int val = FREE_VALUE; | |||
@@ -66,6 +75,9 @@ namespace resumef | |||
#endif | |||
} | |||
/** | |||
* @brief 尝试获得锁一次。 | |||
*/ | |||
bool try_lock() noexcept | |||
{ | |||
int val = FREE_VALUE; | |||
@@ -78,6 +90,9 @@ namespace resumef | |||
return ret; | |||
} | |||
/** | |||
* @brief 释放锁。 | |||
*/ | |||
void unlock() noexcept | |||
{ | |||
#if _DEBUG | |||
@@ -178,17 +193,29 @@ namespace resumef | |||
} | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
// class with destructor that unlocks mutexes | |||
/** | |||
* @brief 无死锁的批量枷锁。 | |||
* @param _Ty 锁的类型。例如std::mutex,resumef::spinlock,resumef::mutex_t(线程用法)均可。 | |||
* @param _Cont 容纳一批锁的容器。 | |||
* @param _Assemble 与_Cont配套的锁集合,特化了如何操作_Ty。 | |||
*/ | |||
template<class _Ty, class _Cont = std::vector<_Ty>, class _Assemble = detail::_LockVectorAssembleT<_Ty, _Cont>> | |||
class batch_lock_t | |||
{ | |||
public: | |||
/** | |||
* @brief 通过锁容器构造,并立刻应用加锁算法。 | |||
*/ | |||
explicit batch_lock_t(_Cont& locks_) | |||
: _LkN(&locks_) | |||
, _LA(*_LkN) | |||
{ | |||
detail::scoped_lock_range_lock_impl::_Lock_range(_LA); | |||
} | |||
/** | |||
* @brief 通过锁容器和锁集合构造,并立刻应用加锁算法。 | |||
*/ | |||
explicit batch_lock_t(_Cont& locks_, _Assemble& la_) | |||
: _LkN(&locks_) | |||
, _LA(la_) | |||
@@ -196,23 +223,36 @@ namespace resumef | |||
detail::scoped_lock_range_lock_impl::_Lock_range(_LA); | |||
} | |||
/** | |||
* @brief 通过锁容器构造,容器里的锁已经全部获得。 | |||
*/ | |||
explicit batch_lock_t(std::adopt_lock_t, _Cont& locks_) | |||
: _LkN(&locks_) | |||
, _LA(*_LkN) | |||
{ // construct but don't lock | |||
} | |||
/** | |||
* @brief 通过锁容器和锁集合构造,容器里的锁已经全部获得。 | |||
*/ | |||
explicit batch_lock_t(std::adopt_lock_t, _Cont& locks_, _Assemble& la_) | |||
: _LkN(&locks_) | |||
, _LA(la_) | |||
{ // construct but don't lock | |||
} | |||
/** | |||
* @brief 析构函数里,释放容器里的锁。 | |||
*/ | |||
~batch_lock_t() noexcept | |||
{ | |||
if (_LkN != nullptr) | |||
detail::scoped_lock_range_lock_impl::_Unlock_locks(0, (int)_LA.size(), _LA); | |||
} | |||
/** | |||
* @brief 手工释放容器里的锁,析构函数里将不再有释放操作。 | |||
*/ | |||
void unlock() | |||
{ | |||
if (_LkN != nullptr) | |||
@@ -222,15 +262,29 @@ namespace resumef | |||
} | |||
} | |||
/** | |||
* @brief 不支持拷贝构造。 | |||
*/ | |||
batch_lock_t(const batch_lock_t&) = delete; | |||
/** | |||
* @brief 不支持拷贝赋值。 | |||
*/ | |||
batch_lock_t& operator=(const batch_lock_t&) = delete; | |||
/** | |||
* @brief 支持移动构造。 | |||
*/ | |||
batch_lock_t(batch_lock_t&& _Right) | |||
: _LkN(_Right._LkN) | |||
, _LA(std::move(_Right._LA)) | |||
{ | |||
_Right._LkN = nullptr; | |||
} | |||
/** | |||
* @brief 支持移动赋值。 | |||
*/ | |||
batch_lock_t& operator=(batch_lock_t&& _Right) | |||
{ | |||
if (this != &_Right) |
@@ -2,6 +2,9 @@ | |||
namespace resumef | |||
{ | |||
/** | |||
* @brief state基类,state用于在协程的promise和future之间共享数据。 | |||
*/ | |||
struct state_base_t | |||
{ | |||
using _Alloc_char = std::allocator<char>; | |||
@@ -61,6 +64,9 @@ namespace resumef | |||
} | |||
}; | |||
/** | |||
* @brief 专用于generator_t<>的state类。 | |||
*/ | |||
struct state_generator_t : public state_base_t | |||
{ | |||
private: | |||
@@ -86,6 +92,9 @@ namespace resumef | |||
static state_generator_t* _Alloc_state(); | |||
}; | |||
/** | |||
* @brief 专用于future_t<>的state基类,实现了针对于future_t<>的公共方法等。 | |||
*/ | |||
struct state_future_t : public state_base_t | |||
{ | |||
enum struct initor_type : uint8_t | |||
@@ -201,6 +210,9 @@ namespace resumef | |||
} | |||
}; | |||
/** | |||
* @brief 专用于future_t<>的state类。 | |||
*/ | |||
template <typename _Ty> | |||
struct state_t final : public state_future_t | |||
{ |
@@ -65,6 +65,7 @@ namespace resumef | |||
//is_container_v<T> | |||
//判断是不是一个封闭区间的容器,或者数组。 | |||
// | |||
//is_container_of<T, E> | |||
//is_container_of_v<T, E> | |||
//判断是不是一个封闭区间的容器,或者数组。其元素类型是E。 | |||
@@ -27,6 +27,10 @@ namespace resumef | |||
} | |||
}; | |||
/** | |||
* @fn 将本协程让渡出一次调用。 | |||
* @return [co_await] void | |||
*/ | |||
inline yield_awaitor yield() | |||
{ | |||
return {}; |