#pragma once #include namespace NYql { /* Let's call 'action' attached functor to future which should be called in the main thread. This trick allows us to execute attached actions not in the future's execution thread but rather in the main thread and preserve single-threaded logic. */ /* Make ready future with constant action inside. */ template NThreading::TFuture> MakeFutureWithConstantAction(const T& value) { return NThreading::MakeFuture>([value]() { return value; }); } template auto AddActionToFuture(NThreading::TFuture f, const A& action) { using V = decltype(action(std::declval())); return f.Apply([action](NThreading::TFuture f) { std::function r = [f, action]() { return action(f.GetValue()); }; return r; }); } /* Apply continuation with constant action */ template NThreading::TFuture> AddConstantActionToFuture(NThreading::TFuture f, const V& value) { return AddActionToFuture(f, [value](const T&) { return value; }); } /* Transform action result by applying mapper */ template auto MapFutureAction(NThreading::TFuture> f, const TMapper& mapper) { using V = decltype(mapper(std::declval())); return f.Apply([mapper](NThreading::TFuture> f) { std::function r = [f, mapper](Args&& ...args) { return mapper(f.GetValue()(std::forward(args)...)); }; return r; }); } }