Add a simple signal implementation to util

This commit is contained in:
Nikita Lisitsa 2023-02-24 15:01:42 +03:00
parent aa61c63609
commit 15b08aeb47

View file

@ -0,0 +1,79 @@
#pragma once
#include <psemek/util/function.hpp>
#include <list>
#include <memory>
namespace psemek::util
{
template <typename T>
struct signal
{
using subscriber = function<void(T const &)>;
using subscription_token = std::shared_ptr<void>;
[[nodiscard]] subscription_token subscribe(subscriber callback) const
{
auto token = std::make_shared<subscriber>(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<std::weak_ptr<subscriber>> subscribers_;
};
template <>
struct signal<void>
{
using subscriber = function<void()>;
using subscribtion_token = std::shared_ptr<void>;
[[nodiscard]] subscribtion_token subscribe(subscriber callback) const
{
auto token = std::make_shared<subscriber>(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<std::weak_ptr<subscriber>> subscribers_;
};
}