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