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