Logo ROOT   6.10/09
Reference Guide
TResultProxy.hxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Danilo Piparo CERN 03/2017
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_TRESULTPROXY
12 #define ROOT_TRESULTPROXY
13 
14 #include "ROOT/TDFNodes.hxx"
15 #include "ROOT/TDFUtils.hxx"
16 
17 #include <memory>
18 
19 namespace ROOT {
20 
21 namespace Experimental {
22 namespace TDF {
23 // Fwd decl for MakeResultProxy
24 template <typename T>
26 }
27 }
28 
29 namespace Detail {
30 namespace TDF {
32 // Fwd decl for TResultProxy
33 template <typename T>
34 TResultProxy<T> MakeResultProxy(const std::shared_ptr<T> &r, const std::shared_ptr<TLoopManager> &df);
35 } // ns TDF
36 } // ns Detail
37 
38 namespace Experimental {
39 namespace TDF {
41 namespace TDFDetail = ROOT::Detail::TDF;
42 
43 /// Smart pointer for the return type of actions
44 /**
45 \class ROOT::Experimental::TDF::TResultProxy
46 \ingroup dataframe
47 \brief A wrapper around the result of TDataFrame actions able to trigger calculations lazily.
48 \tparam T Type of the action result
49 
50 A smart pointer which allows to access the result of a TDataFrame action. The
51 methods of the encapsulated object can be accessed via the arrow operator.
52 Upon invocation of the arrow operator or dereferencing (`operator*`), the
53 loop on the events and calculations of all scheduled actions are executed
54 if needed.
55 It is possible to iterate on the result proxy if the proxied object is a collection.
56 ~~~{.cpp}
57 for (auto& myItem : myResultProxy) { ... };
58 ~~~
59 If iteration is not supported by the type of the proxied object, a compilation error is thrown.
60 
61 */
62 template <typename T>
63 class TResultProxy {
64  /// \cond HIDDEN_SYMBOLS
65  template <typename V, bool isCont = TDFInternal::TIsContainer<V>::fgValue>
66  struct TIterationHelper {
67  using Iterator_t = void;
68  void GetBegin(const V &) { static_assert(sizeof(V) == 0, "It does not make sense to ask begin for this class."); }
69  void GetEnd(const V &) { static_assert(sizeof(V) == 0, "It does not make sense to ask end for this class."); }
70  };
71 
72  template <typename V>
73  struct TIterationHelper<V, true> {
74  using Iterator_t = decltype(std::begin(std::declval<V>()));
75  static Iterator_t GetBegin(const V &v) { return std::begin(v); };
76  static Iterator_t GetEnd(const V &v) { return std::end(v); };
77  };
78  /// \endcond
79  using SPT_t = std::shared_ptr<T>;
80  using SPTLM_t = std::shared_ptr<TDFDetail::TLoopManager>;
81  using WPTLM_t = std::weak_ptr<TDFDetail::TLoopManager>;
82  using ShrdPtrBool_t = std::shared_ptr<bool>;
83  template <typename W>
84  friend TResultProxy<W> TDFDetail::MakeResultProxy(const std::shared_ptr<W> &, const SPTLM_t &);
85 
86  ShrdPtrBool_t fReadiness =
87  std::make_shared<bool>(false); ///< State registered also in the TLoopManager until the event loop is executed
88  WPTLM_t fImplWeakPtr; ///< Points to the TLoopManager at the root of the functional graph
89  SPT_t fObjPtr; ///< Shared pointer encapsulating the wrapped result
90 
91  /// Triggers the event loop in the TLoopManager instance to which it's associated via the fImplWeakPtr
92  void TriggerRun();
93 
94  /// Get the pointer to the encapsulated result.
95  /// Ownership is not transferred to the caller.
96  /// Triggers event loop and execution of all actions booked in the associated TLoopManager.
97  T *Get()
98  {
99  if (!*fReadiness) TriggerRun();
100  return fObjPtr.get();
101  }
102 
103  TResultProxy(const SPT_t &objPtr, const ShrdPtrBool_t &readiness, const SPTLM_t &firstData)
104  : fReadiness(readiness), fImplWeakPtr(firstData), fObjPtr(objPtr)
105  {
106  }
107 
108 public:
109  TResultProxy() = delete;
110 
111  /// Get a const reference to the encapsulated object.
112  /// Triggers event loop and execution of all actions booked in the associated TLoopManager.
113  const T &GetValue()
114  {
115  return *Get();
116  }
117 
118  /// Get a pointer to the encapsulated object.
119  /// Triggers event loop and execution of all actions booked in the associated TLoopManager.
120  T &operator*() { return *Get(); }
121 
122  /// Get a pointer to the encapsulated object.
123  /// Ownership is not transferred to the caller.
124  /// Triggers event loop and execution of all actions booked in the associated TLoopManager.
125  T *operator->() { return Get(); }
126 
127  /// Return an iterator to the beginning of the contained object if this makes
128  /// sense, throw a compilation error otherwise
129  typename TIterationHelper<T>::Iterator_t begin()
130  {
131  if (!*fReadiness) TriggerRun();
132  return TIterationHelper<T>::GetBegin(*fObjPtr);
133  }
134 
135  /// Return an iterator to the end of the contained object if this makes
136  /// sense, throw a compilation error otherwise
137  typename TIterationHelper<T>::Iterator_t end()
138  {
139  if (!*fReadiness) TriggerRun();
140  return TIterationHelper<T>::GetEnd(*fObjPtr);
141  }
142 };
143 
144 template <typename T>
146 {
147  auto df = fImplWeakPtr.lock();
148  if (!df) {
149  throw std::runtime_error("The main TDataFrame is not reachable: did it go out of scope?");
150  }
151  df->Run();
152 }
153 } // end NS TDF
154 } // end NS Experimental
155 
156 namespace Detail {
157 namespace TDF {
158 template <typename T>
159 TResultProxy<T> MakeResultProxy(const std::shared_ptr<T> &r, const std::shared_ptr<TLoopManager> &df)
160 {
161  auto readiness = std::make_shared<bool>(false);
162  auto resPtr = TResultProxy<T>(r, readiness, df);
163  df->Book(readiness);
164  return resPtr;
165 }
166 } // end NS TDF
167 } // end NS Detail
168 } // end NS ROOT
169 
170 #endif // ROOT_TRESULTPROXY
const T & GetValue()
Get a const reference to the encapsulated object.
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
std::shared_ptr< TDFDetail::TLoopManager > SPTLM_t
double T(double x)
Definition: ChebyshevPol.h:34
T * Get()
Get the pointer to the encapsulated result.
std::weak_ptr< TDFDetail::TLoopManager > WPTLM_t
WPTLM_t fImplWeakPtr
Points to the TLoopManager at the root of the functional graph.
Smart pointer for the return type of actions.
SPT_t fObjPtr
Shared pointer encapsulating the wrapped result.
TResultProxy(const SPT_t &objPtr, const ShrdPtrBool_t &readiness, const SPTLM_t &firstData)
TRandom2 r(17)
SVector< double, 2 > v
Definition: Dict.h:5
TIterationHelper< T >::Iterator_t begin()
Return an iterator to the beginning of the contained object if this makes sense, throw a compilation ...
TResultProxy< T > MakeResultProxy(const std::shared_ptr< T > &r, const std::shared_ptr< TLoopManager > &df)
T * operator->()
Get a pointer to the encapsulated object.
std::shared_ptr< bool > ShrdPtrBool_t
void TriggerRun()
Triggers the event loop in the TLoopManager instance to which it&#39;s associated via the fImplWeakPtr...
T & operator*()
Get a pointer to the encapsulated object.
typedef void((*Func_t)())
TIterationHelper< T >::Iterator_t end()
Return an iterator to the end of the contained object if this makes sense, throw a compilation error ...