Implement react::join

This commit is contained in:
Nikita Lisitsa 2023-04-21 17:26:30 +03:00
parent d2afa09adf
commit 2c13bcac15

View file

@ -0,0 +1,59 @@
#pragma once
#include <psemek/react/value.hpp>
namespace psemek::react
{
template <typename T>
value<T> join(value<value<T>> x)
{
auto node = std::make_shared<detail::node<T>>();
auto weak_node = std::weak_ptr{node};
auto internal_subscriber = [weak_node]{
if (auto node = weak_node.lock())
{
node->cached_value = std::nullopt;
node->internal_signal();
}
};
auto inner_external_subscriber = [weak_node](T const &){
if (auto node = weak_node.lock())
if (!node->cached_value)
node->external_signal(node->value());
};
auto inner_internal_token = std::make_shared<util::signal<void>::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){
if (auto node = weak_node.lock())
{
if (!node->cached_value)
{
*inner_internal_token = x.subscribe(detail::internal_tag{}, internal_subscriber);
*inner_external_token = x.subscribe(inner_external_subscriber);
node->external_signal(node->value());
}
}
};
auto internal_token = x.subscribe(detail::internal_tag{}, internal_subscriber);
auto external_token = x.subscribe(external_subscriber);
node->getter = [
inner_internal_token,
inner_external_token,
internal_token,
external_token,
x
]{
return **x;
};
return value<T>(detail::internal_tag{}, std::move(node));
}
}