Add a simple signal implementation to util
This commit is contained in:
parent
aa61c63609
commit
15b08aeb47
1 changed files with 79 additions and 0 deletions
79
libs/util/include/psemek/util/signal.hpp
Normal file
79
libs/util/include/psemek/util/signal.hpp
Normal 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_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue