diff --git a/libs/react/include/psemek/react/join.hpp b/libs/react/include/psemek/react/join.hpp index c7cfb0e7..69c1721c 100644 --- a/libs/react/include/psemek/react/join.hpp +++ b/libs/react/include/psemek/react/join.hpp @@ -25,7 +25,7 @@ namespace psemek::react node->external_signal(node->value()); }; - auto inner_internal_token = std::make_shared::subscription_token>(); + auto inner_internal_token = std::make_shared::subscription_token>(); auto inner_external_token = std::make_shared::subscription_token>(); auto external_subscriber = [weak_node, inner_internal_token, inner_external_token, internal_subscriber, inner_external_subscriber](value const & x){ diff --git a/libs/react/include/psemek/react/map.hpp b/libs/react/include/psemek/react/map.hpp index b7b81f42..b8f26017 100644 --- a/libs/react/include/psemek/react/map.hpp +++ b/libs/react/include/psemek/react/map.hpp @@ -73,7 +73,7 @@ namespace psemek::react } }; - std::vector::subscription_token> internal_tokens; + std::vector::subscription_token> internal_tokens; std::vector::subscription_token> external_tokens; internal_tokens.reserve(args.size()); diff --git a/libs/react/include/psemek/react/source.hpp b/libs/react/include/psemek/react/source.hpp index 8bb50cab..c7c3a632 100644 --- a/libs/react/include/psemek/react/source.hpp +++ b/libs/react/include/psemek/react/source.hpp @@ -80,7 +80,7 @@ namespace psemek::react : value(detail::internal_tag{}, std::make_shared>()) {} - source(util::signal::subscriber subscriber) + source(util::signal<>::subscriber subscriber) : source() { subscribtion_token_ = subscribe(std::move(subscriber)); @@ -96,7 +96,7 @@ namespace psemek::react } private: - util::signal::subscription_token subscribtion_token_; + util::signal<>::subscription_token subscribtion_token_; }; template diff --git a/libs/react/include/psemek/react/value.hpp b/libs/react/include/psemek/react/value.hpp index 8c7c4ad4..ebda9491 100644 --- a/libs/react/include/psemek/react/value.hpp +++ b/libs/react/include/psemek/react/value.hpp @@ -20,7 +20,9 @@ namespace psemek::react template struct node { - util::signal internal_signal; + using external_subscriber = typename util::signal::subscriber; + + util::signal<> internal_signal; util::signal external_signal; util::function getter; std::optional cached_value; @@ -37,8 +39,10 @@ namespace psemek::react template <> struct node { - util::signal internal_signal; - util::signal 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::subscriber subscriber, bool call = false) const + [[nodiscard]] auto subscribe(typename detail::node::external_subscriber subscriber, bool call = false) const { if (call) { diff --git a/libs/ui/include/psemek/ui/impl/container.hpp b/libs/ui/include/psemek/ui/impl/container.hpp index fda743b4..9ecff2f2 100644 --- a/libs/ui/include/psemek/ui/impl/container.hpp +++ b/libs/ui/include/psemek/ui/impl/container.hpp @@ -20,16 +20,16 @@ namespace psemek::ui::impl virtual void set_child_keys(std::vector> keys); virtual std::vector> release_children(); - virtual util::signal::subscription_token release_children_token(); - virtual std::vector::subscription_token> release_child_tokens(); + virtual util::signal<>::subscription_token release_children_token(); + virtual std::vector::subscription_token> release_child_tokens(); virtual std::vector> release_child_keys(); util::span const> children() const override; private: - util::signal::subscription_token children_token_; + util::signal<>::subscription_token children_token_; std::vector> children_; - std::vector::subscription_token> child_tokens_; + std::vector::subscription_token> child_tokens_; std::vector> child_keys_; }; diff --git a/libs/ui/include/psemek/ui/impl/single_container.hpp b/libs/ui/include/psemek/ui/impl/single_container.hpp index 3c685d15..7e0c6b67 100644 --- a/libs/ui/include/psemek/ui/impl/single_container.hpp +++ b/libs/ui/include/psemek/ui/impl/single_container.hpp @@ -15,13 +15,13 @@ namespace psemek::ui::impl util::span const> children() const override; virtual void set_child(std::unique_ptr child); - virtual void set_child_token(util::signal::subscription_token token); + virtual void set_child_token(util::signal<>::subscription_token token); virtual component * child() const; virtual std::unique_ptr release_child(); - virtual util::signal::subscription_token release_child_token(); + virtual util::signal<>::subscription_token release_child_token(); private: - util::signal::subscription_token child_token_; + util::signal<>::subscription_token child_token_; std::unique_ptr child_; }; diff --git a/libs/ui/source/impl/container.cpp b/libs/ui/source/impl/container.cpp index 6ba94b8b..4f59955b 100644 --- a/libs/ui/source/impl/container.cpp +++ b/libs/ui/source/impl/container.cpp @@ -28,12 +28,12 @@ namespace psemek::ui::impl return std::move(children_); } - util::signal::subscription_token container::release_children_token() + util::signal<>::subscription_token container::release_children_token() { return std::move(children_token_); } - std::vector::subscription_token> container::release_child_tokens() + std::vector::subscription_token> container::release_child_tokens() { return std::move(child_tokens_); } diff --git a/libs/ui/source/impl/single_container.cpp b/libs/ui/source/impl/single_container.cpp index d6478103..318c4e48 100644 --- a/libs/ui/source/impl/single_container.cpp +++ b/libs/ui/source/impl/single_container.cpp @@ -13,7 +13,7 @@ namespace psemek::ui::impl child_ = std::move(child); } - void single_container::set_child_token(util::signal::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::subscription_token single_container::release_child_token() + util::signal<>::subscription_token single_container::release_child_token() { return std::move(child_token_); } diff --git a/libs/util/include/psemek/util/signal.hpp b/libs/util/include/psemek/util/signal.hpp index 2134cf72..73893fc0 100644 --- a/libs/util/include/psemek/util/signal.hpp +++ b/libs/util/include/psemek/util/signal.hpp @@ -2,16 +2,17 @@ #include -#include +#include #include namespace psemek::util { - template + template struct signal { - using subscriber = function; + using subscriber = function; + using subscription_token = std::shared_ptr; [[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> subscribers_; - }; - - 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()() - { - 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_; + mutable std::vector> subscribers_; }; }