timemory  3.2.1
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
bundle_execute.hpp
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2020, The Regents of the University of California,
4 // through Lawrence Berkeley National Laboratory (subject to receipt of any
5 // required approvals from the U.S. Dept. of Energy). All rights reserved.
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 
25 #pragma once
26 
29 
30 #include <type_traits>
31 #include <utility>
32 
33 namespace tim
34 {
35 namespace mpl
36 {
37 //
38 template <typename BundleT, typename FuncT, typename... Args>
39 auto
40 execute(BundleT&& _bundle, FuncT&& _func, Args&&... _args,
42  !std::is_void<std::result_of_t<FuncT(Args...)>>::value,
43  int>)
44 {
45  using result_type = std::result_of_t<FuncT(Args...)>;
46  using handler_type = execution_handler<decay_t<BundleT>, result_type>;
47  return handler_type{ std::forward<BundleT>(_bundle),
48  std::forward<FuncT>(_func)(std::forward<Args>(_args)...) };
49 }
50 //
51 template <typename BundleT, typename FuncT, typename... Args>
52 auto
53 execute(BundleT&& _bundle, FuncT&& _func, Args&&... _args,
55  std::is_void<std::result_of_t<FuncT(Args...)>>::value,
56  int>)
57 {
58  _func(std::forward<Args>(_args)...);
59  return std::forward<BundleT>(_bundle);
60 }
61 //
62 template <typename BundleT, typename ValueT>
63 auto
64 execute(BundleT&& _bundle, ValueT&& _value,
66 {
67  using handler_type = execution_handler<decay_t<BundleT>, ValueT>;
68  return handler_type{ std::forward<BundleT>(_bundle), std::forward<ValueT>(_value) };
69 }
70 //
71 template <typename BundleT, typename DataT>
73 {
74 public:
75  static_assert(!std::is_function<DataT>::value,
76  "Error! should be result, not function!");
77 
79 
80  execution_handler() = delete;
83 
84  execution_handler(execution_handler&&) noexcept = default;
85  execution_handler& operator=(execution_handler&&) noexcept = default;
86 
87  execution_handler(BundleT& _bundle, DataT&& _data) noexcept
88  : m_bundle(_bundle)
89  , m_data(std::move(_data))
90  {}
91 
92  operator BundleT() const { return m_bundle; }
93  operator DataT() const { return m_data; }
94  operator std::pair<BundleT, DataT>() const
95  {
96  return std::pair<BundleT, DataT>{ m_bundle, m_data };
97  }
98  operator std::tuple<BundleT, DataT>() const
99  {
100  return std::tuple<BundleT, DataT>{ m_bundle, m_data };
101  }
102 
103  auto get_bundle_and_result() { return std::pair<BundleT, DataT>{ m_bundle, m_data }; }
104 
105  TIMEMORY_NODISCARD auto get_bundle() noexcept { return BundleT{ m_bundle }; }
106  TIMEMORY_NODISCARD auto get_result() noexcept { return DataT{ m_data }; }
107 
108  TIMEMORY_NODISCARD auto& return_bundle() noexcept { return m_bundle; }
109  TIMEMORY_NODISCARD auto return_result() noexcept { return std::move(m_data); }
110 
111  // NOTE: since inheriting from BundleT would result in subsequent functions returning
112  // the this pointer of BundleT, we would discard DataT
113  template <typename... Args>
114  this_type& push(Args&&... args)
115  {
116  m_bundle.push(std::forward<Args>(args)...);
117  return *this;
118  }
119  template <typename... Args>
120  this_type& pop(Args&&... args)
121  {
122  m_bundle.pop(std::forward<Args>(args)...);
123  return *this;
124  }
125  template <typename... Args>
126  this_type& measure(Args&&... args)
127  {
128  m_bundle.measure(std::forward<Args>(args)...);
129  return *this;
130  }
131  template <typename... Args>
132  this_type& sample(Args&&... args)
133  {
134  m_bundle.sample(std::forward<Args>(args)...);
135  return *this;
136  }
137  template <typename... Args>
138  this_type& start(Args&&... args)
139  {
140  m_bundle.start(std::forward<Args>(args)...);
141  return *this;
142  }
143  template <typename... Args>
144  this_type& stop(Args&&... args)
145  {
146  m_bundle.stop(std::forward<Args>(args)...);
147  return *this;
148  }
149  template <typename... Args>
150  this_type& assemble(Args&&... args)
151  {
152  m_bundle.assemble(std::forward<Args>(args)...);
153  return *this;
154  }
155  template <typename... Args>
156  this_type& derive(Args&&... args)
157  {
158  m_bundle.derive(std::forward<Args>(args)...);
159  return *this;
160  }
161  template <typename... Args>
162  this_type& mark(Args&&... args)
163  {
164  m_bundle.mark(std::forward<Args>(args)...);
165  return *this;
166  }
167  template <typename... Args>
168  this_type& mark_begin(Args&&... args)
169  {
170  m_bundle.mark_begin(std::forward<Args>(args)...);
171  return *this;
172  }
173  template <typename... Args>
174  this_type& mark_end(Args&&... args)
175  {
176  m_bundle.mark_end(std::forward<Args>(args)...);
177  return *this;
178  }
179  template <typename... Args>
180  this_type& store(Args&&... args)
181  {
182  m_bundle.store(std::forward<Args>(args)...);
183  return *this;
184  }
185  template <typename... Args>
186  this_type& audit(Args&&... args)
187  {
188  m_bundle.audit(std::forward<Args>(args)...);
189  return *this;
190  }
191  template <typename... Args>
192  this_type& add_secondary(Args&&... args)
193  {
194  m_bundle.add_secondary(std::forward<Args>(args)...);
195  return *this;
196  }
197  template <template <typename> class OpT, typename... Args>
198  this_type& invoke(Args&&... _args)
199  {
200  m_bundle.template invoke<OpT>(std::forward<Args>(_args)...);
201  return *this;
202  }
203  template <typename... Args>
204  decltype(auto) get(Args&&... args)
205  {
206  return execute(*this, m_bundle.get(std::forward<Args>(args)...));
207  }
208  template <typename... Args>
209  decltype(auto) get_labeled(Args&&... args)
210  {
211  return execute(*this, m_bundle.get_labeled(std::forward<Args>(args)...));
212  return m_bundle.get_labeled(std::forward<Args>(args)...);
213  }
214 
215 private:
216  BundleT& m_bundle;
217  DataT m_data;
218 };
219 //
220 //
221 template <typename BundleT>
222 class execution_handler<BundleT, void>
223 {
224 public:
225  using DataT = void;
227 
228  execution_handler() = delete;
231 
232  execution_handler(execution_handler&&) noexcept = default;
233  execution_handler& operator=(execution_handler&&) noexcept = default;
234 
235  execution_handler(BundleT& _bundle) noexcept
236  : m_bundle(_bundle)
237  {}
238 
239  operator BundleT() const { return m_bundle; }
240 
241  operator std::pair<BundleT, null_type>() const
242  {
243  return std::pair<BundleT, DataT>{ m_bundle, null_type{} };
244  }
245 
246  operator std::tuple<BundleT, null_type>() const
247  {
248  return std::tuple<BundleT, DataT>{ m_bundle, null_type{} };
249  }
250 
252  {
253  return std::pair<BundleT, DataT>{ m_bundle, null_type{} };
254  }
255 
256  TIMEMORY_NODISCARD auto& return_bundle() noexcept { return m_bundle; }
257  void return_result() noexcept {}
258 
259  // NOTE: since inheriting from BundleT would result in subsequent functions returning
260  // the this pointer of BundleT, we would discard DataT
261  template <typename... Args>
262  this_type& push(Args&&... args)
263  {
264  m_bundle.push(std::forward<Args>(args)...);
265  return *this;
266  }
267  template <typename... Args>
268  this_type& pop(Args&&... args)
269  {
270  m_bundle.pop(std::forward<Args>(args)...);
271  return *this;
272  }
273  template <typename... Args>
274  this_type& measure(Args&&... args)
275  {
276  m_bundle.measure(std::forward<Args>(args)...);
277  return *this;
278  }
279  template <typename... Args>
280  this_type& sample(Args&&... args)
281  {
282  m_bundle.sample(std::forward<Args>(args)...);
283  return *this;
284  }
285  template <typename... Args>
286  this_type& start(Args&&... args)
287  {
288  m_bundle.start(std::forward<Args>(args)...);
289  return *this;
290  }
291  template <typename... Args>
292  this_type& stop(Args&&... args)
293  {
294  m_bundle.stop(std::forward<Args>(args)...);
295  return *this;
296  }
297  template <typename... Args>
298  this_type& assemble(Args&&... args)
299  {
300  m_bundle.assemble(std::forward<Args>(args)...);
301  return *this;
302  }
303  template <typename... Args>
304  this_type& derive(Args&&... args)
305  {
306  m_bundle.derive(std::forward<Args>(args)...);
307  return *this;
308  }
309  template <typename... Args>
310  this_type& mark(Args&&... args)
311  {
312  m_bundle.mark(std::forward<Args>(args)...);
313  return *this;
314  }
315  template <typename... Args>
316  this_type& mark_begin(Args&&... args)
317  {
318  m_bundle.mark_begin(std::forward<Args>(args)...);
319  return *this;
320  }
321  template <typename... Args>
322  this_type& mark_end(Args&&... args)
323  {
324  m_bundle.mark_end(std::forward<Args>(args)...);
325  return *this;
326  }
327  template <typename... Args>
328  this_type& store(Args&&... args)
329  {
330  m_bundle.store(std::forward<Args>(args)...);
331  return *this;
332  }
333  template <typename... Args>
334  this_type& audit(Args&&... args)
335  {
336  m_bundle.audit(std::forward<Args>(args)...);
337  return *this;
338  }
339  template <typename... Args>
340  this_type& add_secondary(Args&&... args)
341  {
342  m_bundle.add_secondary(std::forward<Args>(args)...);
343  return *this;
344  }
345  template <template <typename> class OpT, typename... Args>
346  this_type& invoke(Args&&... _args)
347  {
348  m_bundle.template invoke<OpT>(std::forward<Args>(_args)...);
349  return *this;
350  }
351  template <typename... Args>
352  decltype(auto) get(Args&&... args)
353  {
354  return execute(*this, m_bundle.get(std::forward<Args>(args)...));
355  }
356  template <typename... Args>
357  decltype(auto) get_labeled(Args&&... args)
358  {
359  return execute(*this, m_bundle.get_labeled(std::forward<Args>(args)...));
360  return m_bundle.get_labeled(std::forward<Args>(args)...);
361  }
362 
363 private:
364  BundleT& m_bundle;
365 };
366 //
367 } // namespace mpl
368 } // namespace tim
execution_handler & operator=(const execution_handler &)=delete
this_type & add_secondary(Args &&... args)
execution_handler(const execution_handler &)=delete
execution_handler(execution_handler &&) noexcept=default
This is an intermediate type that permits operations such as:
this_type & stop(Args &&... args)
this_type & assemble(Args &&... args)
decltype(auto) get(Args &&... args)
execution_handler & operator=(const execution_handler &)=delete
this_type & derive(Args &&... args)
execution_handler(const execution_handler &)=delete
this_type & store(Args &&... args)
this_type & mark(Args &&... args)
execution_handler(execution_handler &&) noexcept=default
this_type & mark_begin(Args &&... args)
this_type & mark_end(Args &&... args)
this_type & start(Args &&... args)
this_type & push(Args &&... args)
this_type & add_secondary(Args &&... args)
auto & return_bundle() noexcept
this_type & audit(Args &&... args)
decltype(auto) get_labeled(Args &&... args)
this_type & invoke(Args &&... _args)
this_type & sample(Args &&... args)
this_type & measure(Args &&... args)
this_type & pop(Args &&... args)
auto execute(BundleT &&_bundle, FuncT &&_func, Args &&... _args, enable_if_t< is_invocable< FuncT, Args... >::value &&!std::is_void< std::result_of_t< FuncT(Args...)>>::value, int >)
Definition: kokkosp.cpp:38
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
this is a placeholder type for optional type-traits. It is used as the default type for the type-trai...
Definition: types.hpp:225