timemory 3.3.0
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
33namespace tim
34{
35namespace mpl
36{
37//
38template <typename BundleT, typename FuncT, typename... Args>
39auto
40execute(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//
51template <typename BundleT, typename FuncT, typename... Args>
52auto
53execute(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//
62template <typename BundleT, typename ValueT>
63auto
64execute(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//
71template <typename BundleT, typename DataT>
73{
74public:
75 static_assert(!std::is_function<DataT>::value,
76 "Error! should be result, not function!");
77
79
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>
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
215private:
216 BundleT& m_bundle;
217 DataT m_data;
218};
219//
220//
221template <typename BundleT>
222class execution_handler<BundleT, void>
223{
224public:
225 using DataT = void;
227
231
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>
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
363private:
364 BundleT& m_bundle;
365};
366//
367} // namespace mpl
368} // namespace tim
execution_handler(const execution_handler &)=delete
execution_handler & operator=(const execution_handler &)=delete
execution_handler(execution_handler &&) noexcept=default
decltype(auto) get_labeled(Args &&... args)
this_type & add_secondary(Args &&... args)
This is an intermediate type that permits operations such as:
this_type & start(Args &&... args)
decltype(auto) get(Args &&... args)
execution_handler & operator=(const execution_handler &)=delete
this_type & add_secondary(Args &&... args)
this_type & stop(Args &&... args)
execution_handler(const execution_handler &)=delete
this_type & measure(Args &&... args)
this_type & mark_end(Args &&... args)
this_type & assemble(Args &&... args)
this_type & store(Args &&... args)
execution_handler(execution_handler &&) noexcept=default
this_type & invoke(Args &&... _args)
this_type & mark_begin(Args &&... args)
this_type & mark(Args &&... args)
decltype(auto) get_labeled(Args &&... args)
this_type & pop(Args &&... args)
auto & return_bundle() noexcept
this_type & sample(Args &&... args)
this_type & derive(Args &&... args)
this_type & audit(Args &&... args)
this_type & push(Args &&... args)
STL namespace.
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:39
std::array< char *, 4 > _args
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