Logo ROOT   master
Reference Guide
TSequentialExecutor.hxx
Go to the documentation of this file.
1 // @(#)root/thread:$Id$
2 // Author: Xavier Valls November 2017
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2006, 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 #ifndef ROOT_TSequentialExecutor
12 #define ROOT_TSequentialExecutor
13 
14 #include "RConfigure.h"
15 
16 #include "ROOT/TExecutor.hxx"
17 #include <numeric>
18 #include <vector>
19 
20 namespace ROOT {
21 
22  class TSequentialExecutor: public TExecutor<TSequentialExecutor> {
23  public:
24  explicit TSequentialExecutor(){};
25 
28 
29  template<class F>
30  void Foreach(F func, unsigned nTimes);
31  template<class F, class INTEGER>
32  void Foreach(F func, ROOT::TSeq<INTEGER> args);
33  /// \cond
34  template<class F, class T>
35  void Foreach(F func, std::initializer_list<T> args);
36  /// \endcond
37  template<class F, class T>
38  void Foreach(F func, std::vector<T> &args);
39 
41  template<class F, class Cond = noReferenceCond<F>>
42  auto Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
43  template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
45  template<class F, class T, class Cond = noReferenceCond<F, T>>
46  auto Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
47 
48  // // MapReduce
49  // // the late return types also check at compile-time whether redfunc is compatible with func,
50  // // other than checking that func is compatible with the type of arguments.
51  // // a static_assert check in TSequentialExecutor::Reduce is used to check that redfunc is compatible with the type returned by func
53  template<class F, class R, class Cond = noReferenceCond<F>>
54  auto MapReduce(F func, unsigned nTimes, R redfunc) -> typename std::result_of<F()>::type;
55  template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
56  auto MapReduce(F func, std::vector<T> &args, R redfunc) -> typename std::result_of<F(T)>::type;
57 
59  template<class T, class R> auto Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs));
60  };
61 
62  /************ TEMPLATE METHODS IMPLEMENTATION ******************/
63 
64  //////////////////////////////////////////////////////////////////////////
65  /// Execute func (with no arguments) nTimes.
66  /// Functions that take more than zero arguments can be executed (with
67  /// fixed arguments) by wrapping them in a lambda or with std::bind.
68  template<class F>
69  void TSequentialExecutor::Foreach(F func, unsigned nTimes) {
70  for (auto i = 0U; i < nTimes; ++i) func();
71  }
72 
73  //////////////////////////////////////////////////////////////////////////
74  /// Execute func, taking an element of a
75  /// sequence as argument.
76  template<class F, class INTEGER>
78  for(auto i : args) func(i);
79  }
80 
81  /// \cond
82  //////////////////////////////////////////////////////////////////////////
83  /// Execute func, taking an element of a
84  /// initializer_list as argument.
85  template<class F, class T>
86  void TSequentialExecutor::Foreach(F func, std::initializer_list<T> args) {
87  std::vector<T> vargs(std::move(args));
88  Foreach(func, vargs);
89  }
90  /// \endcond
91 
92  //////////////////////////////////////////////////////////////////////////
93  /// Execute func, taking an element of an
94  /// std::vector as argument.
95  template<class F, class T>
96  void TSequentialExecutor::Foreach(F func, std::vector<T> &args) {
97  unsigned int nToProcess = args.size();
98  for(auto i: ROOT::TSeqI(nToProcess)) func(args[i]);
99  }
100 
101  //////////////////////////////////////////////////////////////////////////
102  /// Execute func (with no arguments) nTimes.
103  /// A vector containg executions' results is returned.
104  /// Functions that take more than zero arguments can be executed (with
105  /// fixed arguments) by wrapping them in a lambda or with std::bind.
106  template<class F, class Cond>
108  using retType = decltype(func());
109  std::vector<retType> reslist(nTimes);
110  for(auto i: ROOT::TSeqI(nTimes)) reslist[i] = func();
111  return reslist;
112  }
113 
114  //////////////////////////////////////////////////////////////////////////
115  /// Execute func, taking an element of a
116  /// sequence as argument.
117  /// A vector containg executions' results is returned.
118  template<class F, class INTEGER, class Cond>
120  using retType = decltype(func(*args.begin()));
121  std::vector<retType> reslist(args.size());
122  for(auto i: args) reslist[i] = func(i);
123  return reslist;
124  }
125 
126  //////////////////////////////////////////////////////////////////////////
127  /// Execute func, taking an element of an
128  /// std::vector as argument.
129  /// A vector containg executions' results is returned.
130  // actual implementation of the Map method. all other calls with arguments eventually
131  // call this one
132  template<class F, class T, class Cond>
134  // //check whether func is callable
135  using retType = decltype(func(args.front()));
136  unsigned int nToProcess = args.size();
137  std::vector<retType> reslist(nToProcess);
138  for(auto i: ROOT::TSeqI(nToProcess)) reslist[i] = func(args[i]);
139  return reslist;
140  }
141 
142  template<class F, class R, class Cond>
143  auto TSequentialExecutor::MapReduce(F func, unsigned nTimes, R redfunc) -> typename std::result_of<F()>::type {
144  return Reduce(Map(func, nTimes), redfunc);
145  }
146 
147  template<class F, class T, class R, class Cond>
148  auto TSequentialExecutor::MapReduce(F func, std::vector<T> &args, R redfunc) -> typename std::result_of<F(T)>::type {
149  return Reduce(Map(func, args), redfunc);
150  }
151 
152  //////////////////////////////////////////////////////////////////////////
153  /// "Reduce" an std::vector into a single object by passing a
154  /// function as the second argument defining the reduction operation.
155  template<class T, class R>
156  auto TSequentialExecutor::Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs))
157  {
158  // check we can apply reduce to objs
159  static_assert(std::is_same<decltype(redfunc(objs)), T>::value, "redfunc does not have the correct signature");
160  return redfunc(objs);
161  }
162 
163 } // namespace ROOT
164 #endif
Returns the available number of logical cores.
Definition: StringConv.hxx:21
TSequentialExecutor & operator=(TSequentialExecutor &)=delete
auto MapReduce(F func, unsigned nTimes, R redfunc) -> typename std::result_of< F()>::type
double T(double x)
Definition: ChebyshevPol.h:34
auto Map(F func, unsigned nTimes) -> std::vector< typename std::result_of< F()>::type >
Execute func (with no arguments) nTimes.
This class defines an interface to execute the same task multiple times in parallel, possibly with different arguments every time.
Definition: TExecutor.hxx:61
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:110
#define F(x, y, z)
void Foreach(F func, unsigned nTimes)
Execute func (with no arguments) nTimes.
auto Reduce(const std::vector< T > &objs, R redfunc) -> decltype(redfunc(objs))
"Reduce" an std::vector into a single object by passing a function as the second argument defining th...
A pseudo container class which is a generator of indices.
Definition: TSeq.hxx:66
int type
Definition: TGX11.cxx:120
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:909