// Copyright Sebastian Jeckel 2014. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef REACT_ALGORITHM_H_INCLUDED #define REACT_ALGORITHM_H_INCLUDED #pragma once #include "react/detail/Defs.h" #include #include #include #include "react/detail/graph/AlgorithmNodes.h" /*****************************************/ REACT_BEGIN /*****************************************/ /////////////////////////////////////////////////////////////////////////////////////////////////// /// Forward declarations /////////////////////////////////////////////////////////////////////////////////////////////////// template class Signal; template class VarSignal; template class Events; template class EventSource; enum class Token; template class SignalPack; /////////////////////////////////////////////////////////////////////////////////////////////////// /// Hold - Hold the most recent event in a signal /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename V, typename T = typename std::decay::type > auto Hold(const Events& events, V&& init) -> Signal { using REACT_IMPL::HoldNode; return Signal( std::make_shared>( std::forward(init), GetNodePtr(events))); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Monitor - Emits value changes of target signal /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename S > auto Monitor(const Signal& target) -> Events { using REACT_IMPL::MonitorNode; return Events( std::make_shared>( GetNodePtr(target))); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Iterate - Iteratively combines signal value with values from event stream /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename E, typename V, typename FIn, typename S = typename std::decay::type > auto Iterate(const Events& events, V&& init, FIn&& func) -> Signal { using REACT_IMPL::IterateNode; using REACT_IMPL::IterateByRefNode; using F = typename std::decay::type; using R = typename std::result_of::type; using TNode = typename std::conditional< std::is_same::value, IterateByRefNode, IterateNode >::type; return Signal( std::make_shared( std::forward(init), GetNodePtr(events), std::forward(func))); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Iterate - Synced /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename E, typename V, typename FIn, typename ... TDepValues, typename S = typename std::decay::type > auto Iterate(const Events& events, V&& init, const SignalPack& depPack, FIn&& func) -> Signal { using REACT_IMPL::SyncedIterateNode; using REACT_IMPL::SyncedIterateByRefNode; using F = typename std::decay::type; using R = typename std::result_of::type; using TNode = typename std::conditional< std::is_same::value, SyncedIterateByRefNode, SyncedIterateNode >::type; struct NodeBuilder_ { NodeBuilder_(const Events& source, V&& init, FIn&& func) : MySource( source ), MyInit( std::forward(init) ), MyFunc( std::forward(func) ) {} auto operator()(const Signal& ... deps) -> Signal { return Signal( std::make_shared( std::forward(MyInit), GetNodePtr(MySource), std::forward(MyFunc), GetNodePtr(deps) ...)); } const Events& MySource; V MyInit; FIn MyFunc; }; return REACT_IMPL::apply( NodeBuilder_( events, std::forward(init), std::forward(func) ), depPack.Data); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Snapshot - Sets signal value to value of other signal when event is received /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename S, typename E > auto Snapshot(const Events& trigger, const Signal& target) -> Signal { using REACT_IMPL::SnapshotNode; return Signal( std::make_shared>( GetNodePtr(target), GetNodePtr(trigger))); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Pulse - Emits value of target signal when event is received /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename S, typename E > auto Pulse(const Events& trigger, const Signal& target) -> Events { using REACT_IMPL::PulseNode; return Events( std::make_shared>( GetNodePtr(target), GetNodePtr(trigger))); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Changed - Emits token when target signal was changed /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename S > auto Changed(const Signal& target) -> Events { return Monitor(target).Tokenize(); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// ChangedTo - Emits token when target signal was changed to value /////////////////////////////////////////////////////////////////////////////////////////////////// template < typename D, typename V, typename S = typename std::decay::type > auto ChangedTo(const Signal& target, V&& value) -> Events { return Monitor(target) .Filter([=] (const S& v) { return v == value; }) .Tokenize(); } /******************************************/ REACT_END /******************************************/ #endif // REACT_ALGORITHM_H_INCLUDED