// 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