diff --git a/libs/util/include/psemek/util/signal.hpp b/libs/util/include/psemek/util/signal.hpp new file mode 100644 index 00000000..072d6b0e --- /dev/null +++ b/libs/util/include/psemek/util/signal.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include + +#include +#include + +namespace psemek::util +{ + + template + struct signal + { + using subscriber = function; + using subscription_token = std::shared_ptr; + + [[nodiscard]] subscription_token subscribe(subscriber callback) const + { + auto token = std::make_shared(std::move(callback)); + subscribers_.push_back(std::weak_ptr{token}); + return token; + } + + void operator()(T const & value) + { + auto begin = subscribers_.begin(); + auto end = subscribers_.end(); + + for (auto it = begin; it != end;) + { + if (auto callback = it->lock()) + { + (*callback)(value); + ++it; + } + else + it = subscribers_.erase(it); + } + } + + private: + mutable std::list> subscribers_; + }; + + template <> + struct signal + { + using subscriber = function; + using subscribtion_token = std::shared_ptr; + + [[nodiscard]] subscribtion_token subscribe(subscriber callback) const + { + auto token = std::make_shared(std::move(callback)); + subscribers_.push_back(std::weak_ptr{token}); + return token; + } + + void operator()() + { + auto begin = subscribers_.begin(); + auto end = subscribers_.end(); + + for (auto it = begin; it != end;) + { + if (auto callback = it->lock()) + { + (*callback)(); + ++it; + } + else + it = subscribers_.erase(it); + } + } + + private: + mutable std::list> subscribers_; + }; + +}