Skip to content

Commit 3ff8cdc

Browse files
committed
Added EventRange support to Iterate.
1 parent 7948353 commit 3ff8cdc

2 files changed

Lines changed: 138 additions & 64 deletions

File tree

include/react/Algorithm.h

Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ auto Monitor(const Signal<D,S>& target)
7777
}
7878

7979
///////////////////////////////////////////////////////////////////////////////////////////////////
80-
/// Iterate - Iteratively combines signal value with values from event stream
80+
/// Iterate - Iteratively combines signal value with values from event stream (aka Fold)
8181
///////////////////////////////////////////////////////////////////////////////////////////////////
8282
template
8383
<
@@ -92,17 +92,38 @@ auto Iterate(const Events<D,E>& events, V&& init, FIn&& func)
9292
{
9393
using REACT_IMPL::IterateNode;
9494
using REACT_IMPL::IterateByRefNode;
95+
using REACT_IMPL::AddIterateRangeWrapper;
96+
using REACT_IMPL::AddIterateByRefRangeWrapper;
97+
using REACT_IMPL::IsCallableWith;
98+
using REACT_IMPL::EventRange;
9599

96100
using F = typename std::decay<FIn>::type;
97-
using R = typename std::result_of<FIn(E,S&)>::type;
98-
using TNode = typename std::conditional<
99-
std::is_same<void,R>::value,
100-
IterateByRefNode<D,S,E,F>,
101-
IterateNode<D,S,E,F>
102-
>::type;
101+
102+
using NodeT =
103+
typename std::conditional<
104+
IsCallableWith<F,S,EventRange<E>,S>::value,
105+
IterateNode<D,S,E,F>,
106+
typename std::conditional<
107+
IsCallableWith<F,S,E,S>::value,
108+
IterateNode<D,S,E,AddIterateRangeWrapper<E,S,F>>,
109+
typename std::conditional<
110+
IsCallableWith<F, void, EventRange<E>, S&>::value,
111+
IterateByRefNode<D,S,E,F>,
112+
typename std::conditional<
113+
IsCallableWith<F,void,E,S&>::value,
114+
IterateByRefNode<D,S,E,AddIterateByRefRangeWrapper<E,S,F>>,
115+
void
116+
>::type
117+
>::type
118+
>::type
119+
>::type;
120+
121+
static_assert(
122+
! std::is_same<NodeT,void>::value,
123+
"Iterate: Passed function does not match any of the supported signatures.");
103124

104125
return Signal<D,S>(
105-
std::make_shared<TNode>(
126+
std::make_shared<NodeT>(
106127
std::forward<V>(init), GetNodePtr(events), std::forward<FIn>(func)));
107128
}
108129

@@ -124,14 +145,41 @@ auto Iterate(const Events<D,E>& events, V&& init,
124145
{
125146
using REACT_IMPL::SyncedIterateNode;
126147
using REACT_IMPL::SyncedIterateByRefNode;
148+
using REACT_IMPL::AddIterateRangeWrapper;
149+
using REACT_IMPL::AddIterateByRefRangeWrapper;
150+
using REACT_IMPL::IsCallableWith;
151+
using REACT_IMPL::EventRange;
127152

128153
using F = typename std::decay<FIn>::type;
129-
using R = typename std::result_of<FIn(E,S&,TDepValues...)>::type;
130-
using TNode = typename std::conditional<
131-
std::is_same<void,R>::value,
132-
SyncedIterateByRefNode<D,S,E,F,TDepValues ...>,
133-
SyncedIterateNode<D,S,E,F,TDepValues ...>
134-
>::type;
154+
155+
using NodeT =
156+
typename std::conditional<
157+
IsCallableWith<F,S,EventRange<E>,S,TDepValues ...>::value,
158+
SyncedIterateNode<D,S,E,F,TDepValues ...>,
159+
typename std::conditional<
160+
IsCallableWith<F,S,E,S,TDepValues ...>::value,
161+
SyncedIterateNode<D,S,E,
162+
AddIterateRangeWrapper<E,S,F,TDepValues ...>,
163+
TDepValues ...>,
164+
typename std::conditional<
165+
IsCallableWith<F,void,EventRange<E>,S&,TDepValues ...>::value,
166+
SyncedIterateByRefNode<D,S,E,F,TDepValues ...>,
167+
typename std::conditional<
168+
IsCallableWith<F,void,E,S&,TDepValues ...>::value,
169+
SyncedIterateByRefNode<D,S,E,
170+
AddIterateByRefRangeWrapper<E,S,F,TDepValues ...>,
171+
TDepValues ...>,
172+
void
173+
>::type
174+
>::type
175+
>::type
176+
>::type;
177+
178+
static_assert(
179+
! std::is_same<NodeT,void>::value,
180+
"Iterate: Passed function does not match any of the supported signatures.");
181+
182+
//static_assert(NodeT::dummy_error, "DUMP MY TYPE" );
135183

136184
struct NodeBuilder_
137185
{
@@ -145,7 +193,7 @@ auto Iterate(const Events<D,E>& events, V&& init,
145193
-> Signal<D,S>
146194
{
147195
return Signal<D,S>(
148-
std::make_shared<TNode>(
196+
std::make_shared<NodeT>(
149197
std::forward<V>(MyInit), GetNodePtr(MySource),
150198
std::forward<FIn>(MyFunc), GetNodePtr(deps) ...));
151199
}

include/react/detail/graph/AlgorithmNodes.h

Lines changed: 75 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,65 @@
1919

2020
/***************************************/ REACT_IMPL_BEGIN /**************************************/
2121

22+
///////////////////////////////////////////////////////////////////////////////////////////////////
23+
/// AddIterateRangeWrapper
24+
///////////////////////////////////////////////////////////////////////////////////////////////////
25+
template <typename E, typename S, typename F, typename ... TArgs>
26+
struct AddIterateRangeWrapper
27+
{
28+
AddIterateRangeWrapper(const AddIterateRangeWrapper& other) = default;
29+
30+
AddIterateRangeWrapper(AddIterateRangeWrapper&& other) :
31+
MyFunc( std::move(other.MyFunc) )
32+
{}
33+
34+
template
35+
<
36+
typename FIn,
37+
class = typename DisableIfSame<FIn,AddIterateRangeWrapper>::type
38+
>
39+
explicit AddIterateRangeWrapper(FIn&& func) :
40+
MyFunc( std::forward<FIn>(func) )
41+
{}
42+
43+
S operator()(EventRange<E> range, S value, const TArgs& ... args)
44+
{
45+
for (const auto& e : range)
46+
value = MyFunc(e, value, args ...);
47+
48+
return value;
49+
}
50+
51+
F MyFunc;
52+
};
53+
54+
template <typename E, typename S, typename F, typename ... TArgs>
55+
struct AddIterateByRefRangeWrapper
56+
{
57+
AddIterateByRefRangeWrapper(const AddIterateByRefRangeWrapper& other) = default;
58+
59+
AddIterateByRefRangeWrapper(AddIterateByRefRangeWrapper&& other) :
60+
MyFunc( std::move(other.MyFunc) )
61+
{}
62+
63+
template
64+
<
65+
typename FIn,
66+
class = typename DisableIfSame<FIn,AddIterateByRefRangeWrapper>::type
67+
>
68+
explicit AddIterateByRefRangeWrapper(FIn&& func) :
69+
MyFunc( std::forward<FIn>(func) )
70+
{}
71+
72+
void operator()(EventRange<E> range, S& valueRef, const TArgs& ... args)
73+
{
74+
for (const auto& e : range)
75+
MyFunc(e, valueRef, args ...);
76+
}
77+
78+
F MyFunc;
79+
};
80+
2281
///////////////////////////////////////////////////////////////////////////////////////////////////
2382
/// IterateNode
2483
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -65,10 +124,7 @@ class IterateNode :
65124
using TimerT = typename IterateNode::ScopedUpdateTimer;
66125
TimerT scopedTimer( *this, events_->Events().size() );
67126

68-
S newValue = this->value_;
69-
70-
for (const auto& e : events_->Events())
71-
newValue = func_(e, newValue);
127+
S newValue = func_(EventRange<E>( events_->Events() ), this->value_);
72128

73129
if (! Equals(newValue, this->value_))
74130
{
@@ -139,8 +195,8 @@ class IterateByRefNode :
139195
using TimerT = typename IterateByRefNode::ScopedUpdateTimer;
140196
TimerT scopedTimer( *this, events_->Events().size() );
141197

142-
for (const auto& e : events_->Events())
143-
func_(e, this->value_);
198+
func_(EventRange<E>( events_->Events() ), this->value_);
199+
144200
}// ~timer
145201

146202
REACT_LOG(D::Log().template Append<NodeEvaluateEndEvent>(
@@ -203,24 +259,6 @@ class SyncedIterateNode :
203259

204260
virtual void Tick(void* turnPtr) override
205261
{
206-
struct EvalFunctor_
207-
{
208-
EvalFunctor_(const E& e, const S& v, TFunc& f) :
209-
MyEvent( e ),
210-
MyValue( v ),
211-
MyFunc( f )
212-
{}
213-
214-
S operator()(const std::shared_ptr<SignalNode<D,TDepValues>>& ... args)
215-
{
216-
return MyFunc(MyEvent, MyValue, args->ValueRef() ...);
217-
}
218-
219-
const E& MyEvent;
220-
const S& MyValue;
221-
TFunc& MyFunc;
222-
};
223-
224262
using TurnT = typename D::Engine::TurnT;
225263
TurnT& turn = *reinterpret_cast<TurnT*>(turnPtr);
226264

@@ -235,11 +273,13 @@ class SyncedIterateNode :
235273
{// timer
236274
using TimerT = typename SyncedIterateNode::ScopedUpdateTimer;
237275
TimerT scopedTimer( *this, events_->Events().size() );
238-
239-
S newValue = this->value_;
240-
241-
for (const auto& e : events_->Events())
242-
newValue = apply(EvalFunctor_( e, std::move(newValue), func_ ), deps_);
276+
277+
S newValue = apply(
278+
[this] (const std::shared_ptr<SignalNode<D,TDepValues>>& ... args)
279+
{
280+
return func_(EventRange<E>( events_->Events() ), this->value_, args->ValueRef() ...);
281+
},
282+
deps_);
243283

244284
if (! Equals(newValue, this->value_))
245285
{
@@ -313,24 +353,6 @@ class SyncedIterateByRefNode :
313353

314354
virtual void Tick(void* turnPtr) override
315355
{
316-
struct EvalFunctor_
317-
{
318-
EvalFunctor_(const E& e, S& v, TFunc& f) :
319-
MyEvent( e ),
320-
MyValue( v ),
321-
MyFunc( f )
322-
{}
323-
324-
void operator()(const std::shared_ptr<SignalNode<D,TDepValues>>& ... args)
325-
{
326-
MyFunc(MyEvent, MyValue, args->ValueRef() ...);
327-
}
328-
329-
const E& MyEvent;
330-
S& MyValue;
331-
TFunc& MyFunc;
332-
};
333-
334356
using TurnT = typename D::Engine::TurnT;
335357
TurnT& turn = *reinterpret_cast<TurnT*>(turnPtr);
336358

@@ -346,8 +368,12 @@ class SyncedIterateByRefNode :
346368
using TimerT = typename SyncedIterateByRefNode::ScopedUpdateTimer;
347369
TimerT scopedTimer( *this, events_->Events().size() );
348370

349-
for (const auto& e : events_->Events())
350-
apply(EvalFunctor_( e, this->value_, func_ ), deps_);
371+
apply(
372+
[this] (const std::shared_ptr<SignalNode<D,TDepValues>>& ... args)
373+
{
374+
func_(EventRange<E>( events_->Events() ), this->value_, args->ValueRef() ...);
375+
},
376+
deps_);
351377

352378
changed = true;
353379
}// ~timer

0 commit comments

Comments
 (0)