15 #include "RConfigure.h"
19 #include <type_traits>
25 #if !defined(__ROOTCLING__) && !defined(G__DICTIONARY)
26 #error "Cannot use ROOT::Experimental::Async without defining R__USE_IMT."
33 namespace Experimental {
42 friend class Experimental::TFuture;
45 using TTaskGroup = Experimental::TTaskGroup;
46 std::future<T> fStdFut;
47 std::unique_ptr<TTaskGroup> fTg{
nullptr};
49 TFutureImpl(std::future<T> &&fut, std::unique_ptr<TTaskGroup> &&tg) : fStdFut(std::move(fut))
55 TFutureImpl(std::future<T> &&fut) : fStdFut(std::move(fut)) {}
57 TFutureImpl(TFutureImpl<T> &&other) : fStdFut(std::move(other.fStdFut)), fTg(std::move(other.fTg)) {}
59 TFutureImpl &operator=(std::future<T> &&other) { fStdFut = std::move(other); }
61 TFutureImpl<T> &operator=(TFutureImpl<T> &&other) =
default;
64 TFutureImpl<T> &operator=(TFutureImpl<T> &other) =
delete;
66 TFutureImpl(
const TFutureImpl<T> &other) =
delete;
74 bool valid()
const {
return fStdFut.valid(); };
78 namespace Experimental {
83 class TFuture final :
public ROOT::Detail::TFutureImpl<T> {
84 template <
class Function,
class... Args>
86 typename std::result_of<typename std::decay<Function>::type(
typename std::decay<Args>::type...)>::type>
87 Async(Function &&f, Args &&... args);
90 TFuture(std::future<T> &&fut, std::unique_ptr<TTaskGroup> &&tg)
91 : ROOT::Detail::TFutureImpl<T>(std::forward<std::future<T>>(fut), std::move(tg)){};
94 TFuture(std::future<T> &&fut) : ROOT::Detail::TFutureImpl<T>(std::forward<std::future<T>>(fut)){};
99 return this->fStdFut.get();
105 class TFuture<void> final :
public ROOT::Detail::TFutureImpl<void> {
106 template <
class Function,
class... Args>
108 typename std::result_of<typename std::decay<Function>::type(
typename std::decay<Args>::type...)>::type>
109 Async(Function &&f, Args &&... args);
112 TFuture(std::future<void> &&fut, std::unique_ptr<TTaskGroup> &&tg)
113 : ROOT::Detail::TFutureImpl<void>(std::forward<std::future<void>>(fut), std::move(tg)){};
116 TFuture(std::future<void> &&fut) : ROOT::Detail::TFutureImpl<void>(std::forward<std::future<void>>(fut)){};
125 template <
typename T>
126 class TFuture<T &>
final :
public ROOT::Detail::TFutureImpl<T &> {
127 template <
class Function,
class... Args>
129 typename std::result_of<typename std::decay<Function>::type(
typename std::decay<Args>::type...)>::type>
130 Async(Function &&f, Args &&... args);
133 TFuture(std::future<T &> &&fut, std::unique_ptr<TTaskGroup> &&tg)
134 : ROOT::Detail::TFutureImpl<T &>(std::forward<std::future<T &>>(fut), std::move(tg)){};
137 TFuture(std::future<T &> &&fut) : ROOT::Detail::TFutureImpl<T &>(std::forward<std::future<T &>>(fut)){};
142 return this->fStdFut.get();
150 template <
class Function,
class... Args>
151 TFuture<typename std::result_of<typename std::decay<Function>::type(
typename std::decay<Args>::type...)>::type>
152 Async(Function &&f, Args &&... args)
158 using Ret_t =
typename std::result_of<typename std::decay<Function>::type(
typename std::decay<Args>::type...)>::type;
160 auto thisPt = std::make_shared<std::packaged_task<Ret_t()>>(std::bind(f, args...));
161 std::unique_ptr<ROOT::Experimental::TTaskGroup> tg(
new ROOT::Experimental::TTaskGroup());
162 tg->Run([thisPt]() { (*thisPt)(); });
164 return ROOT::Experimental::TFuture<Ret_t>(thisPt->get_future(), std::move(tg));