future_action.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #pragma once
  2. #include <library/cpp/threading/future/future.h>
  3. namespace NYql {
  4. /*
  5. Let's call 'action' attached functor to future which should be called in the main thread.
  6. This trick allows us to execute attached actions not in the future's execution thread but rather in the main thread
  7. and preserve single-threaded logic.
  8. */
  9. /*
  10. Make ready future with constant action inside.
  11. */
  12. template <typename T>
  13. NThreading::TFuture<std::function<T()>> MakeFutureWithConstantAction(const T& value) {
  14. return NThreading::MakeFuture<std::function<T()>>([value]() {
  15. return value;
  16. });
  17. }
  18. template <typename T, typename A>
  19. auto AddActionToFuture(NThreading::TFuture<T> f, const A& action) {
  20. using V = decltype(action(std::declval<T>()));
  21. return f.Apply([action](NThreading::TFuture<T> f) {
  22. std::function<V()> r = [f, action]() {
  23. return action(f.GetValue());
  24. };
  25. return r;
  26. });
  27. }
  28. /*
  29. Apply continuation with constant action
  30. */
  31. template <typename T, typename V>
  32. NThreading::TFuture<std::function<V()>> AddConstantActionToFuture(NThreading::TFuture<T> f, const V& value) {
  33. return AddActionToFuture(f, [value](const T&) { return value; });
  34. }
  35. /*
  36. Transform action result by applying mapper
  37. */
  38. template <typename R, typename TMapper, typename ...Args>
  39. auto MapFutureAction(NThreading::TFuture<std::function<R(Args&&...)>> f, const TMapper& mapper) {
  40. using V = decltype(mapper(std::declval<R>()));
  41. return f.Apply([mapper](NThreading::TFuture<std::function<R(Args&&...)>> f) {
  42. std::function<V(Args&&...)> r = [f, mapper](Args&& ...args) {
  43. return mapper(f.GetValue()(std::forward<Args>(args)...));
  44. };
  45. return r;
  46. });
  47. }
  48. }