// 条件谓词的类型,入参为空且返回值为 bool
using cond_type = std::function<bool()>;
class condition_variable; // 前向声明
using cond_var = condition_variable; // 简化书写
class condition_variable final
{
public:
// 注意这里是对 mutex_awaiter 进行了复用,减少冗余代码
struct cv_awaiter : public mutex::mutex_awaiter
{
friend condition_variable;
// 不支持条件谓词的构造函数
cv_awaiter(context& ctx, mutex& mtx, cond_var& cv) noexcept
: mutex_awaiter(ctx, mtx), // 委托构造
m_cv(cv),
m_suspend_state(false)
{
}
// 支持条件谓词的构造函数
cv_awaiter(context& ctx, mutex& mtx, cond_var& cv, cond_type& cond) noexcept
: mutex_awaiter(ctx, mtx), // 委托构造
m_cv(cv),
m_cond(cond),
m_suspend_state(false)
{
}
// 由于逻辑有变化,需重写原有方法
auto await_suspend(std::coroutine_handle<> handle) noexcept -> bool;
// 由于逻辑有变化,需重写原有方法
auto await_resume() noexcept -> void;
protected:
// 实现了 cv.wait 的核心逻辑,这个命名可能有些误导,后续会修复
auto register_lock() noexcept -> bool;
// 将自身挂载到 cv 的 suspend awaiter 链表中
auto register_cv() noexcept -> void;
// 唤醒 awaiter
auto wake_up() noexcept -> void;
// 尝试恢复 awaiter 运行,该函数会被 wake_up 调用
// 注意这是个虚函数
auto resume() noexcept -> void override;
cond_type m_cond; // 条件谓词
cond_var& m_cv; // 该 awaiter 所依赖的 condition_variable
bool m_suspend_state; // 用来确保 context 的引用计数正常,稍后讲解具体作用
// 这里还需要很多额外的成员变量比如 awaiter 依赖的 context 和 mutex,
// 但通过继承 mutex_awaiter 就不需要再额外定义
};
public:
condition_variable() noexcept = default;
~condition_variable() noexcept;
// 禁止拷贝和移动语义
CORO_NO_COPY_MOVE(condition_variable);
// 条件变量的等待方法,该函数为协程函数
auto wait(mutex& mtx) noexcept -> cv_awaiter;
// 条件变量的等待方法且支持条件谓词,该函数为协程函数
auto wait(mutex& mtx, cond_type&& cond) noexcept -> cv_awaiter;
// 条件变量的等待方法且支持条件谓词,该函数为协程函数
auto wait(mutex& mtx, cond_type& cond) noexcept -> cv_awaiter;
// 通知单个 suspepnd_awaiter 恢复运行,该函数为普通函数
auto notify_one() noexcept -> void;
// 通知所有 suspepnd_awaiter 恢复运行,该函数为普通函数
auto notify_all() noexcept -> void;
private:
detail::spinlock m_lock; // 优化后的自旋锁,也可改用 std::mutex
alignas(config::kCacheLineSize) cv_awaiter* m_head{nullptr}; // suspend awaiter 链表头指针
alignas(config::kCacheLineSize) cv_awaiter* m_tail{nullptr}; // suspend awaiter 链表尾指针
};