| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- #ifndef SOPHIAR2_CORO_SIGNAL_GROUP_HPP
- #define SOPHIAR2_CORO_SIGNAL_GROUP_HPP
- #include "utility/coro_signal2.hpp"
- #include "utility/coro_worker.hpp"
- #include <boost/dynamic_bitset.hpp>
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include <vector>
- namespace sophiar {
- template<auto CondFunc>
- class coro_signal_group {
- public:
- using pointer = std::unique_ptr<coro_signal_group<CondFunc>>;
- coro_signal_group() = default;
- ~coro_signal_group() {
- assert(!is_running);
- }
- static pointer new_instance() {
- return std::make_unique<coro_signal_group<CondFunc>>();
- }
- 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<bool> {
- 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<void> 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<decltype(CondFunc(std::declval<bitset_type &>())), bool>);
- bool is_running = false;
- coro_signal2 final_signal;
- bitset_type item_mask;
- std::vector<signal_watcher> watcher_list;
- std::vector<coro_worker::pointer> 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
|