You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1096 lines
24 KiB

1 year ago
  1. #pragma once
  2. #include "core.h"
  3. #include <memory>
  4. #include <functional>
  5. #include <exception>
  6. #include <future>
  7. #include <vector>
  8. #include <tuple>
  9. #include "refcounted.h"
  10. #include "intrusive_ptr.h"
  11. #include "Try.h"
  12. #include "function_traits.h"
  13. namespace vlc
  14. {
  15. template<typename T> class future;
  16. template<typename T> class promise;
  17. namespace detail
  18. {
  19. template<typename T> class FutureObject : public Refcounted<FutureObject<T>>
  20. {
  21. enum class State : int32_t
  22. {
  23. Start,
  24. ResultSet,
  25. CallbackSet,
  26. Finished
  27. };
  28. public:
  29. using Function = std::function<void(Try<T>&&)>;
  30. FutureObject() : m_state(State::Start)
  31. {
  32. }
  33. explicit FutureObject(Try<T>&& value) :
  34. m_state(State::ResultSet),
  35. m_result(std::move(value))
  36. {
  37. }
  38. inline State state() const
  39. {
  40. return m_state.load(std::memory_order_acquire);
  41. }
  42. bool ready() const
  43. {
  44. switch (state())
  45. {
  46. case State::ResultSet:
  47. case State::Finished:
  48. return true;
  49. default:
  50. return false;
  51. }
  52. }
  53. Try<T>& result()
  54. {
  55. if (ready())
  56. {
  57. return m_result;
  58. }
  59. throw std::logic_error("Future is not ready");
  60. }
  61. template<typename F> void setCallback(F&& f)
  62. {
  63. m_callback = std::forward<F>(f);
  64. for (;;)
  65. {
  66. auto old_state = state();
  67. switch (old_state)
  68. {
  69. case State::Start:
  70. if (m_state.compare_exchange_weak(old_state, State::CallbackSet, std::memory_order_release, std::memory_order_acquire))
  71. return;
  72. // State has changed. Reload value and try again
  73. break;
  74. case State::ResultSet:
  75. m_state.store(State::Finished, std::memory_order_relaxed);
  76. fireAndRelease();
  77. return;
  78. default:
  79. throw std::logic_error("Invalid state");
  80. }
  81. }
  82. }
  83. void setResult(Try<T>&& value)
  84. {
  85. m_result = std::move(value);
  86. for (;;)
  87. {
  88. auto old_state = state();
  89. switch (old_state)
  90. {
  91. case State::Start:
  92. m_lock.lock();
  93. if (m_state.compare_exchange_weak(old_state, State::ResultSet, std::memory_order_release, std::memory_order_acquire))
  94. {
  95. m_lock.unlock();
  96. cv.notify_all();
  97. return;
  98. }
  99. m_lock.unlock();
  100. // State has changed. Reload value and try again
  101. break;
  102. case State::CallbackSet:
  103. m_state.store(State::Finished, std::memory_order_relaxed);
  104. fireAndRelease();
  105. return;
  106. default:
  107. throw std::logic_error("Invalid state");
  108. }
  109. }
  110. }
  111. void wait() const
  112. {
  113. std::unique_lock<std::mutex> lk(m_lock);
  114. assert(state() == State::Start || state() == State::ResultSet);
  115. cv.wait(lk, [this]() { return state() == State::ResultSet; });
  116. assert(state() == State::ResultSet);
  117. }
  118. template<class Rep, class Period>
  119. bool wait_for(const std::chrono::duration<Rep, Period>& timeout_duration) const
  120. {
  121. std::unique_lock<std::mutex> lk(m_lock);
  122. assert(state() == State::Start || state() == State::ResultSet);
  123. bool status = cv.wait_for(lk, timeout_duration, [this]() { return state() == State::ResultSet; });
  124. assert(status || !(state() == State::ResultSet));
  125. return status;
  126. }
  127. template<class Clock, class Duration>
  128. bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time) const
  129. {
  130. std::unique_lock<std::mutex> lk(m_lock);
  131. assert(state() == State::Start || state() == State::ResultSet);
  132. bool status = cv.wait_until(lk, timeout_time, [this]() { return state() == State::ResultSet; });
  133. return status;
  134. }
  135. private:
  136. void fireAndRelease()
  137. {
  138. assert(m_callback);
  139. assert(m_state == State::Finished);
  140. m_callback(std::move(m_result));
  141. m_callback = nullptr;
  142. }
  143. std::atomic<State> m_state;
  144. Function m_callback;
  145. Try<T> m_result;
  146. mutable std::condition_variable cv;
  147. mutable std::mutex m_lock;
  148. };
  149. template<typename T> struct IsFuture : std::false_type
  150. {
  151. using type = T;
  152. };
  153. template<typename T> struct IsFuture<future<T>> : std::true_type
  154. {
  155. using type = T;
  156. };
  157. template<typename F, typename... Args>
  158. using result_of = decltype(std::declval<F>()(std::declval<Args>()...));
  159. template<bool IsTry, typename F, typename... Args>
  160. struct ArgResult
  161. {
  162. using Result = result_of<F, Args...>;
  163. };
  164. template<typename F, typename... Args>
  165. struct IsCallableWith
  166. {
  167. template<typename T, typename = result_of<T, Args...>>
  168. static constexpr std::true_type check(std::nullptr_t);
  169. template<typename>
  170. static constexpr std::false_type check(...);
  171. static constexpr bool value = decltype(check<F>(nullptr))::value;
  172. };
  173. template<typename T, typename F>
  174. struct CallableResult
  175. {
  176. using Argument =
  177. typename std::conditional<
  178. IsCallableWith<F>::value, ArgResult<false, F>,
  179. typename std::conditional<
  180. IsCallableWith<F, T&&>::value, ArgResult<false, F, T&&>,
  181. typename std::conditional<
  182. IsCallableWith<F, T&>::value, ArgResult<false, F, T&>,
  183. typename std::conditional<
  184. IsCallableWith<F, Try<T>&&>::value, ArgResult<true, F, Try<T>&&>,
  185. ArgResult<true, F, Try<T>&>
  186. >::type
  187. >::type
  188. >::type
  189. >::type;
  190. using ReturnsFuture = IsFuture<typename Argument::Result>;
  191. using Result = future<typename ReturnsFuture::type>;
  192. };
  193. template<typename F>
  194. struct CallableResult<void, F>
  195. {
  196. using Argument =
  197. typename std::conditional <
  198. IsCallableWith<F>::value, ArgResult<false, F>,
  199. typename std::conditional<
  200. IsCallableWith<F, Try<void>&&>::value, ArgResult<true, F, Try<void>&&>,
  201. ArgResult<true, F, Try<void>&>
  202. >::type
  203. >::type;
  204. using ReturnsFuture = IsFuture<typename Argument::Result>;
  205. using Result = future<typename ReturnsFuture::type>;
  206. };
  207. template<typename T> struct FunctionReferenceToPointer
  208. {
  209. using type = T;
  210. };
  211. template<typename R, typename... Args> struct FunctionReferenceToPointer<R(&)(Args...)>
  212. {
  213. using type = R(*)(Args...);
  214. };
  215. template<typename... Args> struct Passables : public Refcounted<Passables<Args...>>
  216. {
  217. using TupleType = std::tuple<typename std::decay<Args>::type...>;
  218. TupleType t;
  219. Passables(std::tuple<Args...>&& v) : t(std::move(v))
  220. {
  221. }
  222. template<typename... SourceArgs> Passables(SourceArgs&&... args) : t(std::forward<SourceArgs>(args)...)
  223. {
  224. }
  225. Passables(Passables&& src)
  226. {
  227. std::swap(t, src.t);
  228. }
  229. Passables& operator = (Passables&& src)
  230. {
  231. std::swap(t, src.t);
  232. return *this;
  233. }
  234. template<size_t idx> auto arg() -> typename std::tuple_element<idx, TupleType>::type &
  235. {
  236. return std::get<idx>(t);
  237. }
  238. template<size_t idx> auto arg() const -> const typename std::tuple_element<idx, TupleType>::type&
  239. {
  240. return std::get<idx>(t);
  241. }
  242. Passables(const Passables&) = delete;
  243. Passables& operator = (const Passables&) = delete;
  244. };
  245. }
  246. template<typename T> class future
  247. {
  248. public:
  249. using value_type = T;
  250. future() noexcept = default;
  251. ~future() = default;
  252. future(const future&) = delete;
  253. future& operator = (const future&) = delete;
  254. future(future&& src) noexcept : m_obj(std::move(src.m_obj))
  255. {
  256. }
  257. future& operator = (future&& src) noexcept
  258. {
  259. std::swap(m_obj, src.m_obj);
  260. return *this;
  261. }
  262. template<typename ValueType = T, typename =
  263. typename std::enable_if<!detail::IsFuture<typename std::decay<ValueType>::type>::value>::type
  264. >
  265. future(ValueType&& value) :
  266. m_obj(new detail::FutureObject<T>(Try<T>(std::forward<ValueType>(value))))
  267. {
  268. }
  269. bool valid() const noexcept
  270. {
  271. return (bool)m_obj;
  272. }
  273. bool ready() const
  274. {
  275. return valid() ? m_obj->ready() : false;
  276. }
  277. future& wait()
  278. {
  279. if (ready())
  280. {
  281. return *this;
  282. }
  283. throwIfInvalid();
  284. m_obj->wait();
  285. return *this;
  286. }
  287. template<class Rep, class Period>
  288. bool wait_for(const std::chrono::duration<Rep, Period>& timeout_time) const
  289. {
  290. if (ready())
  291. {
  292. return true;
  293. }
  294. throwIfInvalid();
  295. return m_obj->wait_for(timeout_time);
  296. }
  297. template<class Clock, class Duration>
  298. bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time) const
  299. {
  300. if (ready())
  301. {
  302. return true;
  303. }
  304. throwIfInvalid();
  305. return m_obj->wait_until(timeout_time);
  306. }
  307. T get()
  308. {
  309. return std::move(wait().value());
  310. }
  311. typename std::add_lvalue_reference<T>::type
  312. value()
  313. {
  314. throwIfInvalid();
  315. return m_obj->result().value();
  316. }
  317. typename std::add_lvalue_reference<const T>::type
  318. value() const
  319. {
  320. throwIfInvalid();
  321. return m_obj->result().value();
  322. }
  323. template<typename F,
  324. typename FP = typename detail::FunctionReferenceToPointer<F>::type,
  325. typename R = detail::CallableResult<T, FP>>
  326. typename R::Result then(F&& func)
  327. {
  328. using Arguments = typename R::Argument;
  329. return then_impl<FP, R>(std::forward<FP>(func), Arguments());
  330. }
  331. template<typename F> future<T> on_exception(F&& func)
  332. {
  333. return on_error_impl(std::forward<F>(func));
  334. }
  335. template<typename F> future<T> ensure(F&& func)
  336. {
  337. auto pt = make_intrusive<detail::Passables<F>>(std::forward<F>(func));
  338. return then([pt](Try<T>&& result)
  339. {
  340. std::move(pt->template arg<0>())();
  341. return make_future(std::move(result));
  342. });
  343. }
  344. /// Internal methods
  345. using FutureObjectPtr = IntrusivePtr<detail::FutureObject<T>>;
  346. template<typename F> void setCallback(F&& func)
  347. {
  348. throwIfInvalid();
  349. m_obj->setCallback(std::forward<F>(func));
  350. }
  351. private:
  352. FutureObjectPtr m_obj;
  353. template<typename U> friend class promise;
  354. template<typename U> friend future<U> make_future(Try<U>&&);
  355. explicit future(FutureObjectPtr obj) : m_obj(obj)
  356. {
  357. }
  358. void throwIfInvalid() const
  359. {
  360. if (!m_obj)
  361. {
  362. throw std::future_error(std::future_errc::no_state);
  363. }
  364. }
  365. template<typename F, typename R, bool isTry, typename... Args>
  366. typename std::enable_if<!R::ReturnsFuture::value, typename R::Result>::type
  367. // If returns T
  368. then_impl(F&& func, detail::ArgResult<isTry, F, Args...>)
  369. {
  370. static_assert(sizeof...(Args) <= 1, "then callback must accept one or zero arguments");
  371. throwIfInvalid();
  372. using RetType = typename R::ReturnsFuture::type;
  373. promise<RetType> p;
  374. auto f = p.get_future();
  375. auto pt = make_intrusive<detail::Passables<promise<RetType>, F>>(std::move(p), std::forward<F>(func));
  376. setCallback([pt](Try<T>&& result) mutable
  377. {
  378. auto&& pm = pt->template arg<0>();
  379. auto&& func = pt->template arg<1>();
  380. if (!isTry && result.isFailure())
  381. {
  382. pm.set_exception(std::move(result.exception()));
  383. }
  384. else
  385. {
  386. pm.set_with([&]
  387. {
  388. return std::move(func)(result.template get<isTry, Args>()...);
  389. });
  390. }
  391. });
  392. return f;
  393. }
  394. template<typename F, typename R, bool isTry, typename... Args>
  395. typename std::enable_if<R::ReturnsFuture::value, typename R::Result>::type
  396. // If returns future<T>
  397. then_impl(F&& func, detail::ArgResult<isTry, F, Args...>)
  398. {
  399. static_assert(sizeof...(Args) <= 1, "then callback must accept one or zero arguments");
  400. throwIfInvalid();
  401. using RetType = typename R::ReturnsFuture::type;
  402. promise<RetType> p;
  403. auto f = p.get_future();
  404. auto pt = make_intrusive<detail::Passables<promise<RetType>, F>>(std::move(p), std::forward<F>(func));
  405. setCallback([pt](Try<T>&& result) mutable
  406. {
  407. auto&& pm = pt->template arg<0>();
  408. auto&& func = pt->template arg<1>();
  409. std::exception_ptr exc;
  410. if (result.isFailure())
  411. {
  412. exc = std::move(result.exception());
  413. }
  414. else
  415. {
  416. try
  417. {
  418. auto f2 = std::move(func)(result.template get<isTry, Args>()...);
  419. f2.setCallback([pt](Try<RetType>&& result2)
  420. {
  421. pt->template arg<0>().set_try(std::move(result2));
  422. });
  423. }
  424. catch (...)
  425. {
  426. exc = std::current_exception();
  427. }
  428. }
  429. if (exc)
  430. {
  431. pm.set_exception(exc);
  432. }
  433. });
  434. return f;
  435. }
  436. template<typename F, typename R = typename function_traits<F>::result_type>
  437. // If callback returns T
  438. typename std::enable_if<!detail::IsFuture<R>::value, future<T>>::type on_error_impl(F&& func)
  439. {
  440. using Exc = typename function_traits<F>::template arg<0>::type;
  441. static_assert(std::is_same<R, T>::value, "Return type of on_error callback must be T or future<T>");
  442. promise<T> p;
  443. auto f = p.get_future();
  444. auto pt = make_intrusive<detail::Passables<promise<T>, F>>(std::move(p), std::forward<F>(func));
  445. setCallback([pt](Try<T>&& result) mutable
  446. {
  447. if (!result.template recoverWith<Exc>([&](Exc& e)
  448. {
  449. auto&& pm = pt->template arg<0>();
  450. auto&& func = pt->template arg<1>();
  451. pm.set_with([&]
  452. {
  453. return std::move(func)(e);
  454. });
  455. }))
  456. {
  457. pt->template arg<0>().set_try(std::move(result));
  458. }
  459. });
  460. return f;
  461. }
  462. template<typename F, typename R = typename function_traits<F>::result_type>
  463. // If callback returns future<T>
  464. typename std::enable_if<detail::IsFuture<R>::value, future<T>>::type on_error_impl(F&& func)
  465. {
  466. using Exc = typename function_traits<F>::template arg<0>::type;
  467. static_assert(std::is_same<R, future<T>>::value, "Return type of on_error callback must be T or future<T>");
  468. promise<T> p;
  469. auto f = p.get_future();
  470. auto pt = make_intrusive<detail::Passables<promise<T>, F>>(std::move(p), std::forward<F>(func));
  471. setCallback([pt](Try<T>&& result)
  472. {
  473. auto&& pm = pt->template arg<0>();
  474. if (!result.template recoverWith<Exc>([&](Exc& e)
  475. {
  476. auto&& f = pt->template arg<1>();
  477. std::exception_ptr exc;
  478. try
  479. {
  480. auto f2 = std::move(f)(e);
  481. f2.setCallback([pt](Try<T>&& result2) mutable
  482. {
  483. auto&& pm = pt->template arg<0>();
  484. pm.set_try(std::move(result2));
  485. });
  486. }
  487. catch (...)
  488. {
  489. exc = std::current_exception();
  490. }
  491. if (exc)
  492. {
  493. pm.set_exception(std::move(exc));
  494. }
  495. }))
  496. {
  497. auto&& pm = pt->template arg<0>();
  498. pm.set_try(std::move(result));
  499. }
  500. });
  501. return f;
  502. }
  503. };
  504. template<typename T> class promise
  505. {
  506. public:
  507. promise() : m_obj(new detail::FutureObject<T>())
  508. {
  509. }
  510. ~promise()
  511. {
  512. if (m_obj)
  513. {
  514. if (m_future_retrieved && !m_obj->ready())
  515. {
  516. m_obj->setResult(Try<T>(std::make_exception_ptr(std::future_error(std::future_errc::broken_promise))));
  517. }
  518. }
  519. }
  520. promise(const promise&) = delete;
  521. promise& operator = (const promise&) = delete;
  522. promise(promise&& src) noexcept :
  523. m_obj(std::move(src.m_obj)),
  524. m_future_retrieved(src.m_future_retrieved)
  525. {
  526. src.m_future_retrieved = false;
  527. }
  528. promise& operator = (promise&& src) noexcept
  529. {
  530. std::swap(m_obj, src.m_obj);
  531. std::swap(m_future_retrieved, src.m_future_retrieved);
  532. return *this;
  533. }
  534. future<T> get_future()
  535. {
  536. throwIfRetrieved();
  537. m_future_retrieved = true;
  538. return future<T>(m_obj);
  539. }
  540. void set_try(Try<T>&& t)
  541. {
  542. throwIfFulfilled();
  543. m_obj->setResult(std::move(t));
  544. }
  545. template<typename ValueType> void set_value(const ValueType& value)
  546. {
  547. throwIfFulfilled();
  548. m_obj->setResult(Try<T>(value));
  549. }
  550. template<typename ValueType> void set_value(ValueType&& value)
  551. {
  552. throwIfFulfilled();
  553. m_obj->setResult(Try<T>(std::forward<ValueType>(value)));
  554. }
  555. void set_exception(std::exception_ptr exc)
  556. {
  557. throwIfFulfilled();
  558. m_obj->setResult(Try<T>(exc));
  559. }
  560. template<typename F> void set_with(F&& setter)
  561. {
  562. throwIfFulfilled();
  563. m_obj->setResult(make_try_with(std::forward<F>(setter)));
  564. }
  565. private:
  566. using FutureObjectPtr = IntrusivePtr<detail::FutureObject<T>>;
  567. FutureObjectPtr m_obj;
  568. bool m_future_retrieved = false;
  569. void throwIfRetrieved()
  570. {
  571. if (m_future_retrieved)
  572. {
  573. throw std::future_error(std::future_errc::future_already_retrieved);
  574. }
  575. }
  576. void throwIfFulfilled()
  577. {
  578. if (!m_obj)
  579. {
  580. throw std::future_error(std::future_errc::no_state);
  581. }
  582. if (m_obj->ready())
  583. {
  584. throw std::future_error(std::future_errc::promise_already_satisfied);
  585. }
  586. }
  587. };
  588. /// Helpers
  589. template<typename T> future<T> make_future(Try<T>&& t)
  590. {
  591. return future<T>(make_intrusive<detail::FutureObject<T>>(std::move(t)));
  592. }
  593. template<typename T>
  594. future<typename std::decay<T>::type> make_future(T&& value)
  595. {
  596. using DecayedType = typename std::decay<T>::type;
  597. return make_future(Try<DecayedType>(std::forward<T>(value)));
  598. }
  599. template<typename T> future<T> make_future(const std::exception_ptr& e)
  600. {
  601. return make_future(Try<T>(e));
  602. }
  603. template<typename T, typename E>
  604. typename std::enable_if<std::is_base_of<std::exception, E>::value, future<T>>::type
  605. make_future(const E& e)
  606. {
  607. return make_future(std::make_exception_ptr(e));
  608. }
  609. template<typename F, typename R = typename function_traits<F>::result_type>
  610. typename std::enable_if<detail::IsFuture<R>::value, R>::type
  611. make_future_with(F&& func)
  612. {
  613. using T = typename detail::IsFuture<R>::type;
  614. try
  615. {
  616. return func();
  617. }
  618. catch (...)
  619. {
  620. return make_future<T>(std::current_exception());
  621. }
  622. }
  623. template<typename F, typename R = typename function_traits<F>::result_type>
  624. typename std::enable_if<!detail::IsFuture<R>::value, future<R>>::type
  625. make_future_with(F&& func)
  626. {
  627. return make_future<R>(make_try_with([&func]() mutable
  628. {
  629. return func();
  630. }));
  631. }
  632. inline future<void> make_future()
  633. {
  634. return future<void>();
  635. }
  636. template<typename Iterator, typename F,
  637. typename IteratorValueType = typename std::iterator_traits<Iterator>::value_type,
  638. typename ResultType = typename decltype(std::declval<IteratorValueType>().then(std::declval<F>()))::value_type
  639. >
  640. auto map(Iterator first, Iterator last, F&& func) -> std::vector<future<ResultType>>
  641. {
  642. std::vector<future<ResultType>> result(std::distance(first, last));
  643. for (size_t id = 0; first != last; ++first, ++id)
  644. {
  645. result[id] = first->then(std::forward<F>(func));
  646. }
  647. return result;
  648. }
  649. template<typename Container, typename F>
  650. auto map(Container&& c, F&& f) -> decltype(map(c.begin(), c.end(), f))
  651. {
  652. return map(c.begin(), c.end(), std::forward<F>(f));
  653. }
  654. namespace detail
  655. {
  656. template<typename T> struct Collector
  657. {
  658. using ResultType = std::vector<T>;
  659. explicit Collector(size_t n) : result(n), has_exception(false)
  660. {
  661. }
  662. ~Collector()
  663. {
  664. if (!has_exception)
  665. {
  666. p.set_value(std::move(result));
  667. }
  668. }
  669. void setResult(uint32_t i, Try<T>& t)
  670. {
  671. result[i] = std::move(t.value());
  672. }
  673. promise<ResultType> p;
  674. ResultType result;
  675. std::atomic<bool> has_exception;
  676. };
  677. template<> struct Collector<void>
  678. {
  679. using ResultType = void;
  680. explicit Collector(size_t) : has_exception(false)
  681. {
  682. }
  683. ~Collector()
  684. {
  685. if (!has_exception)
  686. {
  687. p.set_value(Try<void>());
  688. }
  689. }
  690. void setResult(uint32_t, Try<void>&)
  691. {
  692. }
  693. promise<void> p;
  694. std::atomic<bool> has_exception;
  695. };
  696. template<typename ValueType> struct CollectorAll
  697. {
  698. using ResultType = std::vector<Try<ValueType>>;
  699. CollectorAll(size_t n) : results(n)
  700. {
  701. }
  702. ~CollectorAll()
  703. {
  704. p.set_value(std::move(results));
  705. }
  706. void setResult(uint32_t i, Try<ValueType>&& t)
  707. {
  708. results[i] = std::forward<Try<ValueType>>(t);
  709. }
  710. promise<ResultType> p;
  711. ResultType results;
  712. };
  713. template<> struct CollectorAll<void>
  714. {
  715. using ResultType = void;
  716. CollectorAll(size_t)
  717. {
  718. }
  719. ~CollectorAll()
  720. {
  721. p.set_value(Try<ResultType>());
  722. }
  723. void setResult(uint32_t, Try<ResultType>&&)
  724. {
  725. }
  726. promise<ResultType> p;
  727. };
  728. template<typename Iterator> using TypeFromIterator =
  729. typename std::iterator_traits<Iterator>::value_type;
  730. }
  731. /// Like collectAll, but will short circuit on the first exception. Thus, the
  732. /// type of the returned Future is std::vector<T> instead of
  733. /// std::vector<Try<T>>
  734. template<typename Iterator> auto collect(Iterator first, Iterator last) ->
  735. future<typename detail::Collector<typename detail::TypeFromIterator<Iterator>::value_type>::ResultType>
  736. {
  737. using ValueType = typename detail::TypeFromIterator<Iterator>::value_type;
  738. auto ctx = std::make_shared<detail::Collector<ValueType>>(std::distance(first, last));
  739. uint32_t id = 0;
  740. for (; first != last; ++first, ++id)
  741. {
  742. first->setCallback([id, ctx](Try<ValueType>&& t)
  743. {
  744. if (t.isFailure())
  745. {
  746. if (!ctx->has_exception.exchange(true))
  747. {
  748. ctx->p.set_exception(std::move(t.exception()));
  749. }
  750. }
  751. else if (!ctx->has_exception)
  752. {
  753. ctx->setResult(id, t);
  754. }
  755. });
  756. }
  757. return ctx->p.get_future();
  758. }
  759. template<typename Container> auto collect(Container&& c) -> decltype(collect(c.begin(), c.end()))
  760. {
  761. return collect(c.begin(), c.end());
  762. }
  763. /**
  764. When all the input Futures complete, the returned Future will complete.
  765. Errors do not cause early termination; this Future will always succeed
  766. after all its Futures have finished (whether successfully or with an
  767. error).
  768. The Futures are moved in, so your copies are invalid. If you need to
  769. chain further from these Futures, use the variant with an output iterator.
  770. */
  771. template<typename Iterator> auto collectAll(Iterator first, Iterator last) ->
  772. future<typename detail::CollectorAll<typename detail::TypeFromIterator<Iterator>::value_type>::ResultType>
  773. {
  774. using ValueType = typename detail::TypeFromIterator<Iterator>::value_type;
  775. auto ctx = std::make_shared<detail::CollectorAll<ValueType>>(std::distance(first, last));
  776. uint32_t id = 0;
  777. for (; first != last; ++first, ++id)
  778. {
  779. first->setCallback([id, ctx](Try<ValueType>&& t)
  780. {
  781. ctx->setResult(id, std::forward<Try<ValueType>>(t));
  782. });
  783. }
  784. return ctx->p.get_future();
  785. }
  786. template<typename Container> auto collectAll(Container&& c) -> decltype(collectAll(c.begin(), c.end()))
  787. {
  788. return collectAll(c.begin(), c.end());
  789. }
  790. namespace detail
  791. {
  792. template<typename... Ts> struct CollectorVariadic
  793. {
  794. promise<std::tuple<Ts...>> p;
  795. std::tuple<Try<Ts>...> result;
  796. std::atomic<bool> has_exception;
  797. using ResultType = future<std::tuple<Ts...>>;
  798. CollectorVariadic() : has_exception(false)
  799. {
  800. }
  801. ~CollectorVariadic()
  802. {
  803. if (!has_exception)
  804. {
  805. p.set_value(unwrap_tuple(std::move(result)));
  806. }
  807. }
  808. CollectorVariadic(const CollectorVariadic&) = delete;
  809. CollectorVariadic& operator = (const CollectorVariadic&) = delete;
  810. template<size_t i, typename T> void set_result(Try<T>& t)
  811. {
  812. if (t.isFailure())
  813. {
  814. if (!has_exception.exchange(true))
  815. {
  816. p.set_exception(t.exception());
  817. }
  818. }
  819. else if (!has_exception)
  820. {
  821. std::get<i>(result) = std::move(t);
  822. }
  823. }
  824. };
  825. template<typename... Ts> struct CollectorAllVariadic
  826. {
  827. promise<std::tuple<Try<Ts>...>> p;
  828. std::tuple<Try<Ts>...> result;
  829. using ResultType = future<std::tuple<Try<Ts>...>>;
  830. CollectorAllVariadic() = default;
  831. ~CollectorAllVariadic()
  832. {
  833. p.set_value(std::move(result));
  834. }
  835. template<size_t i, typename T> void set_result(Try<T>& t)
  836. {
  837. std::get<i>(result) = std::move(t);
  838. }
  839. };
  840. template< template<typename...> class Ctx, typename... Ts> void setCallbackCollectorVariadic(const std::shared_ptr<Ctx<Ts...>>&)
  841. {
  842. }
  843. template< template<typename...> class Ctx, typename... Ts, typename Head, typename... Rest>
  844. void setCallbackCollectorVariadic(const std::shared_ptr<Ctx<Ts...>>& ctx, Head&& head, Rest&&... rest)
  845. {
  846. head.setCallback([ctx](Try<typename Head::value_type>&& t)
  847. {
  848. ctx->template set_result<sizeof...(Ts)-sizeof...(Rest)-1>(t);
  849. });
  850. setCallbackCollectorVariadic(ctx, std::forward<Rest>(rest)...);
  851. }
  852. }
  853. template<typename... Futures> auto collect(Futures&&... fs) -> typename detail::CollectorVariadic<typename std::decay<Futures>::type::value_type...>::ResultType
  854. {
  855. auto ctx = std::make_shared<detail::CollectorVariadic<typename std::decay<Futures>::type::value_type...>>();
  856. detail::setCallbackCollectorVariadic(ctx, std::forward<typename std::decay<Futures>::type>(fs)...);
  857. return ctx->p.get_future();
  858. }
  859. template<typename... Futures> auto collectAll(Futures&&... fs) -> typename detail::CollectorAllVariadic<typename std::decay<Futures>::type::value_type...>::ResultType
  860. {
  861. auto ctx = std::make_shared<detail::CollectorAllVariadic<typename std::decay<Futures>::type::value_type...>>();
  862. detail::setCallbackCollectorVariadic(ctx, std::forward<typename std::decay<Futures>::type>(fs)...);
  863. return ctx->p.get_future();
  864. }
  865. }