#ifndef SOPHIAR2_CORO_SIGNAL_GROUP_HPP #define SOPHIAR2_CORO_SIGNAL_GROUP_HPP #include "utility/coro_signal2.hpp" #include "utility/coro_worker.hpp" #include #include #include #include #include namespace sophiar { template class coro_signal_group { public: using pointer = std::unique_ptr>; coro_signal_group() = default; ~coro_signal_group() { assert(!is_running); } static pointer new_instance() { return std::make_unique>(); } void add_watcher(signal_watcher &&watcher) { assert(!is_running); watcher_list.push_back(std::move(watcher)); } auto new_watcher() { return final_signal.new_watcher(); } void start(bool auto_sync = true) { // 思考如果 auto_sync == false 有什么副作用? assert(!is_running); item_mask.resize(watcher_list.size()); is_running = true; for (size_t index = 0; index < watcher_list.size(); ++index) { auto worker = make_infinite_coro_worker([this, index, auto_sync]() -> boost::asio::awaitable { co_await watcher_list[index].coro_wait(auto_sync); item_mask.set(index); check_and_notify(); co_return true; }); worker->run(); worker_list.push_back(std::move(worker)); } } boost::asio::awaitable stop() { for (auto &worker: worker_list) { worker->cancel(); } for (auto &worker: worker_list) { co_await worker->coro_wait_stop(); } worker_list.clear(); is_running = false; } private: using bitset_type = boost::dynamic_bitset<>; static_assert(std::is_convertible_v())), bool>); bool is_running = false; coro_signal2 final_signal; bitset_type item_mask; std::vector watcher_list; std::vector worker_list; void check_and_notify() { if (!CondFunc(item_mask)) return; item_mask.reset(); final_signal.try_notify_all(); } }; using coro_signal_all_group = coro_signal_group<[](auto &mask) { return mask.all(); }>; using coro_signal_any_group = coro_signal_group<[](auto &mask) { return mask.any(); }>; } #endif //SOPHIAR2_CORO_SIGNAL_GROUP_HPP