Browse Source

继续完善文档

tags/v2.9.7
tearshark 4 years ago
parent
commit
e13f2b09b6

+ 2
- 1
Doxyfile View File

@@ -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.

+ 7
- 0
librf/src/asio_task_1.12.0.inl View File

@@ -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 {

+ 41
- 1
librf/src/awaitable.h View File

@@ -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
{

+ 1
- 0
librf/src/channel_v2.h View File

@@ -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;


+ 37
- 4
librf/src/counted_ptr.h View File

@@ -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();

+ 10
- 0
librf/src/current_scheduler.h View File

@@ -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 {};

+ 29
- 10
librf/src/exception.inl View File

@@ -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;

+ 6
- 0
librf/src/future.h View File

@@ -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
{

+ 5
- 2
librf/src/generator.h View File

@@ -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();

+ 3
- 3
librf/src/mutex_v2.inl View File

@@ -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);
}
}


+ 45
- 0
librf/src/sleep.h View File

@@ -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_)
{

+ 55
- 1
librf/src/spinlock.h View File

@@ -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)

+ 12
- 0
librf/src/state.h View File

@@ -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
{

+ 1
- 0
librf/src/type_traits.inl View File

@@ -65,6 +65,7 @@ namespace resumef
//is_container_v<T>
//判断是不是一个封闭区间的容器,或者数组。
//
//is_container_of<T, E>
//is_container_of_v<T, E>
//判断是不是一个封闭区间的容器,或者数组。其元素类型是E。


+ 4
- 0
librf/src/yield.h View File

@@ -27,6 +27,10 @@ namespace resumef
}
};

/**
* @fn 将本协程让渡出一次调用。
* @return [co_await] void
*/
inline yield_awaitor yield()
{
return {};

Loading…
Cancel
Save