Guest User

Untitled

a guest
Nov 11th, 2020
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.63 KB | None | 0 0
  1.  
  2. namespace stdcoro = std;
  3.  
  4.  
  5. template<typename Callable, typename Tuple, std::size_t... Is >
  6. constexpr auto tupleApplyImpl( Callable&& _toCall, const Tuple& _tuple, std::index_sequence<Is...> )
  7. {
  8.     return (_toCall( std::get<Is>( _tuple ) ), ...);
  9. }
  10. template<typename Callable, typename ... ArgsList >
  11. constexpr auto tupleApply( Callable&& _toCall , const std::tuple<ArgsList...>& _tuple )
  12. {
  13.     return tupleApplyImpl( std::forward<Callable>( _toCall ), _tuple, std::index_sequence_for<ArgsList...>{} );
  14. }
  15.  
  16.  
  17. template <typename... Args>
  18. struct stdcoro::coroutine_traits<void, Args...> {
  19.     struct promise_type {
  20.         void get_return_object() {}
  21.         stdcoro::suspend_never initial_suspend() { return {}; }
  22.         stdcoro::suspend_never final_suspend()noexcept { return {}; }
  23.         void return_void() {}
  24.         void unhandled_exception() { std::terminate(); }
  25.     };
  26. };
  27.  
  28.  
  29. namespace CoroUtils
  30. {
  31.  
  32.  
  33. template<typename... Tasks>
  34. void makeTaskSequence(Tasks&&... tasks)
  35. {
  36.     (co_await tasks, ...);
  37. }
  38.  
  39. struct WhenAllReadyCounter
  40. {
  41.     WhenAllReadyCounter(size_t _countTo)
  42.         :   m_suspendedCoroutine{nullptr}
  43.         ,   m_whenAllCounter{ _countTo +1}
  44.     {
  45.     }
  46.  
  47.     void setCoroutineForWaiting( stdcoro::coroutine_handle<> _awaitingCoroutine )noexcept
  48.     {
  49.         m_suspendedCoroutine = _awaitingCoroutine;
  50.         m_whenAllCounter.fetch_sub(1, std::memory_order_acq_rel);
  51.     }
  52.  
  53.     void notifyAwaitingCompleted()noexcept
  54.     {
  55.         const size_t countValue{ m_whenAllCounter.fetch_sub(1,std::memory_order_acq_rel) };
  56.         if(countValue == 1)
  57.         {
  58.             m_suspendedCoroutine.resume();
  59.         }
  60.     }
  61.  
  62.     stdcoro::coroutine_handle<> m_suspendedCoroutine;
  63.     std::atomic<size_t> m_whenAllCounter;
  64. };
  65.  
  66. template<typename Task>
  67. struct WhenAllTask
  68. {
  69.  
  70.     WhenAllTask(Task _task)
  71.         :   m_taskItem{ _task }
  72.         ,   m_whenAllCounter{nullptr}
  73.     {
  74.     }
  75.     bool await_ready() const noexcept
  76.     {
  77.         return false;
  78.     }
  79.  
  80.     void await_resume() const noexcept
  81.     {
  82.         m_whenAllCounter->notifyAwaitingCompleted();
  83.     }
  84.  
  85.     void await_suspend(stdcoro::coroutine_handle<> thisCoroutine) noexcept
  86.     {
  87.         co_await m_taskItem;
  88.         thisCoroutine.resume();
  89.     }
  90.  
  91.     void setTimer(WhenAllReadyCounter* _pCounter)
  92.     {
  93.        m_whenAllCounter = _pCounter;
  94.     }
  95.  
  96.     Task m_taskItem;
  97.     WhenAllReadyCounter* m_whenAllCounter;
  98. };
  99.  
  100. template<typename ...Awaitables>
  101. auto when_all(Awaitables&&... _awaitablesList)
  102. {
  103.     struct WhenAllAwaitable
  104.     {
  105.  
  106.         using TTaskTuple = std::tuple<WhenAllTask<Awaitables>...>;
  107.         TTaskTuple m_taskList;
  108.         WhenAllReadyCounter m_whenAllCounter;
  109.  
  110.         bool await_ready() const noexcept
  111.         {
  112.             return false;
  113.         }
  114.         TTaskTuple& await_resume()noexcept
  115.         {
  116.             return m_taskList;
  117.         }
  118.  
  119.         void await_suspend(stdcoro::coroutine_handle<> thisCoroutine) noexcept
  120.         {
  121.             m_whenAllCounter.setCoroutineForWaiting(thisCoroutine);
  122.             std::apply(
  123.                     [this](auto& ... task)
  124.                     {
  125.                         (task.setTimer(&m_whenAllCounter), ...);
  126.                     }
  127.                 ,   m_taskList
  128.             );
  129.             std::apply(
  130.                     [](auto&... _task)
  131.                     {
  132.                         return makeTaskSequence(_task...);
  133.                     }
  134.                 ,   m_taskList
  135.             );
  136.         }
  137.     };
  138.  
  139.     return WhenAllAwaitable{
  140.             std::forward_as_tuple(_awaitablesList...)
  141.         ,   sizeof...(_awaitablesList)
  142.     };
  143. }
  144.  
  145. }
  146.  
  147.  
Advertisement
Add Comment
Please, Sign In to add comment