|
I have advanced a bit in my understanding of the use of fix0 function. It is fixed point combinator for a function that takes no arguments and returns void, i.e. for a work function passed to scheduler's Schedule() call.
The problem that is solves here is defining a recursive function inline. One obvious approach, as shown below, won't work because the reference to the recursive function will go out of scope as soon as enclosing function gets executed.
std::function<void()> work;
work = [=,&work]()
{
try {
if (state->cancel)
return;
if (!state->rem)
{
observer->OnCompleted();
}
else
{
observer->OnNext(state->i);
--state->rem;
++state->i;
DefaultScheduler::Instance().Schedule(work);
}
} catch (...) {
observer->OnError(std::current_exception());
}
};
DefaultScheduler::Instance().Schedule(work);
Another solution, that will work, is to stuff the function object into the state object. State object persists because it is wrapped in shared pointer.
return CreateObservable<Integral>(
[=](std::shared_ptr<Observer<Integral>> observer) -> Disposable
{
struct State
{
bool cancel;
Integral i;
Integral rem;
std::function<void()> work;
};
auto state = std::make_shared<State>();
state->cancel = false;
state->i = start;
state->rem = (end - start) / step;
state->work = [=]()
{
try {
if (state->cancel)
return;
if (!state->rem)
{
observer->OnCompleted();
}
else
{
observer->OnNext(state->i);
--state->rem;
++state->i;
DefaultScheduler::Instance().Schedule(state->work);
}
} catch (...) {
observer->OnError(std::current_exception());
}
};
DefaultScheduler::Instance().Schedule(state->work);
return [=]{ state->cancel = true; };
});
}
There are reasons (maybe not really applicable to this particular case, but good reasons nonetheless) to avoid this solution with function variable and to use fixed point combinator instead. See Wes Dyer explanation for C# at : http://blogs.msdn.com/b/wesdyer/archive/2007/02/02/anonymous-recursion-in-c.aspx
Of course, I still don't understand what TODO comment next to use of fix0 means. It implies something still needs to be done, but says nothing about what and why.
|