// 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 (aka Fold) /////////////////////////////////////////////////////////////////////////////////////////////////// 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 REACT_IMPL::AddIterateRangeWrapper; using REACT_IMPL::AddIterateByRefRangeWrapper; using REACT_IMPL::IsCallableWith; using REACT_IMPL::EventRange; using F = typename std::decay::type; using NodeT = typename std::conditional< IsCallableWith,S>::value, IterateNode, typename std::conditional< IsCallableWith::value, IterateNode>, typename std::conditional< IsCallableWith, S&>::value, IterateByRefNode, typename std::conditional< IsCallableWith::value, IterateByRefNode>, void >::type >::type >::type >::type; static_assert( ! std::is_same::value, "Iterate: Passed function does not match any of the supported signatures."); 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 REACT_IMPL::AddIterateRangeWrapper; using REACT_IMPL::AddIterateByRefRangeWrapper; using REACT_IMPL::IsCallableWith; using REACT_IMPL::EventRange; using F = typename std::decay::type; using NodeT = typename std::conditional< IsCallableWith,S,TDepValues ...>::value, SyncedIterateNode, typename std::conditional< IsCallableWith::value, SyncedIterateNode, TDepValues ...>, typename std::conditional< IsCallableWith,S&,TDepValues ...>::value, SyncedIterateByRefNode, typename std::conditional< IsCallableWith::value, SyncedIterateByRefNode, TDepValues ...>, void >::type >::type >::type >::type; static_assert( ! std::is_same::value, "Iterate: Passed function does not match any of the supported signatures."); //static_assert(NodeT::dummy_error, "DUMP MY 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