Logo ROOT   6.12/07
Reference Guide
TFuture.hxx
Go to the documentation of this file.
1 // @(#)root/thread:$Id$
2 // Author: Danilo Piparo August 2017
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TFuture
13 #define ROOT_TFuture
14 
15 #include "RConfigure.h"
16 
17 #include "ROOT/TTaskGroup.hxx"
18 
19 #include <type_traits>
20 #include <future>
21 
22 // exclude in case ROOT does not have IMT support
23 #ifndef R__USE_IMT
24 // No need to error out for dictionaries.
25 #if !defined(__ROOTCLING__) && !defined(G__DICTIONARY)
26 #error "Cannot use ROOT::Experimental::Async without defining R__USE_IMT."
27 #endif
28 #else
29 
30 namespace ROOT {
31 
32 // fwd declaration
33 namespace Experimental {
34 template <typename T>
35 class TFuture;
36 }
37 
38 namespace Detail {
39 template <typename T>
40 class TFutureImpl {
41  template <typename V>
42  friend class Experimental::TFuture;
43 
44 protected:
46  std::future<T> fStdFut;
47  std::unique_ptr<TTaskGroup> fTg{nullptr};
48 
49  TFutureImpl(std::future<T> &&fut, std::unique_ptr<TTaskGroup> &&tg) : fStdFut(std::move(fut))
50  {
51  fTg = std::move(tg);
52  };
54 
55  TFutureImpl(std::future<T> &&fut) : fStdFut(std::move(fut)) {}
56 
57  TFutureImpl(TFutureImpl<T> &&other) : fStdFut(std::move(other.fStdFut)), fTg(std::move(other.fTg)) {}
58 
59  TFutureImpl &operator=(std::future<T> &&other) { fStdFut = std::move(other); }
60 
61  TFutureImpl<T> &operator=(TFutureImpl<T> &&other) = default;
62 
63 public:
64  TFutureImpl<T> &operator=(TFutureImpl<T> &other) = delete;
65 
66  TFutureImpl(const TFutureImpl<T> &other) = delete;
67 
68  void wait()
69  {
70  if (fTg)
71  fTg->Wait();
72  }
73 
74  bool valid() const { return fStdFut.valid(); };
75 };
76 }
77 
78 namespace Experimental {
79 
80 ////////////////////////////////////////////////////////////////////////////////
81 /// A TFuture class. It can wrap an std::future.
82 template <typename T>
83 class TFuture final : public ROOT::Detail::TFutureImpl<T> {
84  template <class Function, class... Args>
85  friend TFuture<
87  Async(Function &&f, Args &&... args);
88 
89 private:
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)){};
92 
93 public:
94  TFuture(std::future<T> &&fut) : ROOT::Detail::TFutureImpl<T>(std::forward<std::future<T>>(fut)){};
95 
96  T get()
97  {
98  this->wait();
99  return this->fStdFut.get();
100  }
101 };
102 /// \cond
103 // Two specialisations, for void and T& as for std::future
104 template <>
105 class TFuture<void> final : public ROOT::Detail::TFutureImpl<void> {
106  template <class Function, class... Args>
107  friend TFuture<
109  Async(Function &&f, Args &&... args);
110 
111 private:
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)){};
114 
115 public:
116  TFuture(std::future<void> &&fut) : ROOT::Detail::TFutureImpl<void>(std::forward<std::future<void>>(fut)){};
117 
118  void get()
119  {
120  this->wait();
121  fStdFut.get();
122  }
123 };
124 
125 template <typename T>
126 class TFuture<T &> final : public ROOT::Detail::TFutureImpl<T &> {
127  template <class Function, class... Args>
128  friend TFuture<
130  Async(Function &&f, Args &&... args);
131 
132 private:
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)){};
135 
136 public:
137  TFuture(std::future<T &> &&fut) : ROOT::Detail::TFutureImpl<T &>(std::forward<std::future<T &>>(fut)){};
138 
139  T &get()
140  {
141  this->wait();
142  return this->fStdFut.get();
143  }
144 };
145 /// \endcond
146 
147 ////////////////////////////////////////////////////////////////////////////////
148 /// Runs a function asynchronously potentially in a new thread and returns a
149 /// ROOT TFuture that will hold the result.
150 template <class Function, class... Args>
152 Async(Function &&f, Args &&... args)
153 {
154  // The return type according to the standard implementation of std::future
155  // the long type is due to the fact that we want to be c++11 compatible.
156  // A more elegant version would be:
157  // std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
159 
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)(); });
163 
164  return ROOT::Experimental::TFuture<Ret_t>(thisPt->get_future(), std::move(tg));
165 }
166 }
167 }
168 
169 #endif
170 #endif
TFutureImpl(std::future< T > &&fut, std::unique_ptr< TTaskGroup > &&tg)
Definition: TFuture.hxx:49
std::future< T > fStdFut
Definition: TFuture.hxx:46
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
double T(double x)
Definition: ChebyshevPol.h:34
TFuture< typename std::result_of< typename std::decay< Function >::type(typename std::decay< Args >::type...)>::type > Async(Function &&f, Args &&... args)
Runs a function asynchronously potentially in a new thread and returns a ROOT TFuture that will hold ...
Definition: TFuture.hxx:152
STL namespace.
TFuture(std::future< T > &&fut, std::unique_ptr< TTaskGroup > &&tg)
Definition: TFuture.hxx:90
Double_t(* Function)(Double_t)
Definition: Functor.C:4
TFutureImpl(std::future< T > &&fut)
Definition: TFuture.hxx:55
A class to manage the asynchronous execution of work items.
Definition: TTaskGroup.hxx:21
TFuture(std::future< T > &&fut)
Definition: TFuture.hxx:94
TFutureImpl(TFutureImpl< T > &&other)
Definition: TFuture.hxx:57
A TFuture class. It can wrap an std::future.
Definition: TFuture.hxx:35
int type
Definition: TGX11.cxx:120
void forward(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData)
apply the weights (and functions) in forward direction of the DNN
Definition: NeuralNet.icc:545
Binding & operator=(OUT(*fun)(void))
TFutureImpl & operator=(std::future< T > &&other)
Definition: TFuture.hxx:59