Optimize util::signal & support signal<Args...>

This commit is contained in:
Nikita Lisitsa 2023-06-20 02:11:49 +03:00
parent d7c8d8710c
commit 4befa1cad7
9 changed files with 44 additions and 62 deletions

View file

@ -25,7 +25,7 @@ namespace psemek::react
node->external_signal(node->value());
};
auto inner_internal_token = std::make_shared<util::signal<void>::subscription_token>();
auto inner_internal_token = std::make_shared<util::signal<>::subscription_token>();
auto inner_external_token = std::make_shared<typename util::signal<T>::subscription_token>();
auto external_subscriber = [weak_node, inner_internal_token, inner_external_token, internal_subscriber, inner_external_subscriber](value<T> const & x){

View file

@ -73,7 +73,7 @@ namespace psemek::react
}
};
std::vector<util::signal<void>::subscription_token> internal_tokens;
std::vector<util::signal<>::subscription_token> internal_tokens;
std::vector<typename util::signal<T>::subscription_token> external_tokens;
internal_tokens.reserve(args.size());

View file

@ -80,7 +80,7 @@ namespace psemek::react
: value<void>(detail::internal_tag{}, std::make_shared<detail::node<void>>())
{}
source(util::signal<void>::subscriber subscriber)
source(util::signal<>::subscriber subscriber)
: source()
{
subscribtion_token_ = subscribe(std::move(subscriber));
@ -96,7 +96,7 @@ namespace psemek::react
}
private:
util::signal<void>::subscription_token subscribtion_token_;
util::signal<>::subscription_token subscribtion_token_;
};
template <typename T>

View file

@ -20,7 +20,9 @@ namespace psemek::react
template <typename T>
struct node
{
util::signal<void> internal_signal;
using external_subscriber = typename util::signal<T>::subscriber;
util::signal<> internal_signal;
util::signal<T> external_signal;
util::function<T()> getter;
std::optional<T> cached_value;
@ -37,8 +39,10 @@ namespace psemek::react
template <>
struct node<void>
{
util::signal<void> internal_signal;
util::signal<void> external_signal;
using external_subscriber = typename util::signal<>::subscriber;
util::signal<> internal_signal;
util::signal<> external_signal;
void value()
{}
@ -99,7 +103,7 @@ namespace psemek::react
return node_->value();
}
[[nodiscard]] auto subscribe(typename util::signal<T>::subscriber subscriber, bool call = false) const
[[nodiscard]] auto subscribe(typename detail::node<T>::external_subscriber subscriber, bool call = false) const
{
if (call)
{

View file

@ -20,16 +20,16 @@ namespace psemek::ui::impl
virtual void set_child_keys(std::vector<std::optional<key>> keys);
virtual std::vector<std::unique_ptr<component>> release_children();
virtual util::signal<void>::subscription_token release_children_token();
virtual std::vector<util::signal<void>::subscription_token> release_child_tokens();
virtual util::signal<>::subscription_token release_children_token();
virtual std::vector<util::signal<>::subscription_token> release_child_tokens();
virtual std::vector<std::optional<key>> release_child_keys();
util::span<std::unique_ptr<component> const> children() const override;
private:
util::signal<void>::subscription_token children_token_;
util::signal<>::subscription_token children_token_;
std::vector<std::unique_ptr<component>> children_;
std::vector<util::signal<void>::subscription_token> child_tokens_;
std::vector<util::signal<>::subscription_token> child_tokens_;
std::vector<std::optional<key>> child_keys_;
};

View file

@ -15,13 +15,13 @@ namespace psemek::ui::impl
util::span<std::unique_ptr<component> const> children() const override;
virtual void set_child(std::unique_ptr<component> child);
virtual void set_child_token(util::signal<void>::subscription_token token);
virtual void set_child_token(util::signal<>::subscription_token token);
virtual component * child() const;
virtual std::unique_ptr<component> release_child();
virtual util::signal<void>::subscription_token release_child_token();
virtual util::signal<>::subscription_token release_child_token();
private:
util::signal<void>::subscription_token child_token_;
util::signal<>::subscription_token child_token_;
std::unique_ptr<component> child_;
};

View file

@ -28,12 +28,12 @@ namespace psemek::ui::impl
return std::move(children_);
}
util::signal<void>::subscription_token container::release_children_token()
util::signal<>::subscription_token container::release_children_token()
{
return std::move(children_token_);
}
std::vector<util::signal<void>::subscription_token> container::release_child_tokens()
std::vector<util::signal<>::subscription_token> container::release_child_tokens()
{
return std::move(child_tokens_);
}

View file

@ -13,7 +13,7 @@ namespace psemek::ui::impl
child_ = std::move(child);
}
void single_container::set_child_token(util::signal<void>::subscription_token token)
void single_container::set_child_token(util::signal<>::subscription_token token)
{
child_token_ = std::move(token);
}
@ -28,7 +28,7 @@ namespace psemek::ui::impl
return std::move(child_);
}
util::signal<void>::subscription_token single_container::release_child_token()
util::signal<>::subscription_token single_container::release_child_token()
{
return std::move(child_token_);
}

View file

@ -2,16 +2,17 @@
#include <psemek/util/function.hpp>
#include <list>
#include <vector>
#include <memory>
namespace psemek::util
{
template <typename T>
template <typename ... Args>
struct signal
{
using subscriber = function<void(T const &)>;
using subscriber = function<void(Args const & ...)>;
using subscription_token = std::shared_ptr<void>;
[[nodiscard]] subscription_token subscribe(subscriber callback) const
@ -21,59 +22,36 @@ namespace psemek::util
return token;
}
void operator()(T const & value)
void operator()(Args const & ... args)
{
auto begin = subscribers_.begin();
auto end = subscribers_.end();
auto subscribers = std::move(subscribers_);
auto begin = subscribers.begin();
auto end = subscribers.end();
auto alive_end = begin;
for (auto it = begin; it != end;)
{
if (auto callback = it->lock())
{
(*callback)(value);
(*callback)(args...);
if (alive_end != it)
*alive_end = std::move(*it);
++it;
++alive_end;
}
else
it = subscribers_.erase(it);
++it;
}
subscribers.erase(alive_end, end);
for (auto & s : subscribers_)
subscribers.push_back(std::move(s));
subscribers_ = std::move(subscribers);
}
private:
mutable std::list<std::weak_ptr<subscriber>> subscribers_;
};
template <>
struct signal<void>
{
using subscriber = function<void()>;
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()()
{
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_;
mutable std::vector<std::weak_ptr<subscriber>> subscribers_;
};
}