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.
auto_base_bundle.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
26#pragma once
27
37
38#include <cstdint>
39#include <string>
40
41namespace tim
42{
43/// \class tim::auto_base_bundle
44/// \brief Static polymorphic base class for automatic start/stop bundlers
45//
46/// \class tim::auto_base_bundle< Tag, CompT, BundleT >
47/// \tparam Tag Unique identifying type for the bundle which when \ref
48/// tim::trait::is_available<Tag> is false at compile-time or \ref
49/// tim::trait::runtime_enabled<Tag>() is false at runtime, then none of the components
50/// will be collected
51/// \tparam CompT The empty or empty + tag non-auto type which will be wrapped
52/// \tparam BundleT Derived data type
53///
54/// \brief Example:
55/// `auto_base_bundle<Tag, component_bundle<Tag>, auto_bundle<Tag, Types...>>` will
56/// use `Tag` + `trait::is_available<Tag>` or `trait::runtime_available<Tag>` to disable
57/// this bundle at compile-time or run-time, respectively. It will wrap auto-start/stop
58/// around `component_bundle<Tag, Types...>` and use `auto_bundle<Tag, Types...>` for
59/// function signatures.
60template <typename Tag, typename CompT, typename BundleT>
61class auto_base_bundle<Tag, CompT, BundleT>
62: public concepts::wrapper
63, public concepts::variadic
65, public concepts::tagged
66{
67 static_assert(concepts::is_api<Tag>::value,
68 "Error! The first template parameter of an 'BundleT' must "
69 "statisfy the 'is_api' concept");
70
71public:
72 using this_type = BundleT;
75 using component_type = typename base_type::component_type;
76 using tuple_type = typename component_type::tuple_type;
78 using sample_type = typename component_type::sample_type;
79 using bundle_type = typename component_type::bundle_type;
80 using initializer_type = std::function<void(this_type&)>;
82 using captured_location_t = typename component_type::captured_location_t;
84
85 static constexpr bool has_gotcha_v = component_type::has_gotcha_v;
86 static constexpr bool has_user_bundle_v = component_type::has_user_bundle_v;
87
88public:
89 template <typename T, typename... U>
91 tim::variadic::impl::quirk_config<T, convert_t<BundleT, type_list<>>, U...>;
92
93public:
94 //
95 static void init_storage() { component_type::init_storage(); }
96 //
98 {
99 static initializer_type _instance = [](this_type&) {};
100 return _instance;
101 }
102 //
104 {
105 static initializer_type _instance = [](this_type&) {};
106 return _instance;
107 }
108
109public:
111
112 template <typename... T>
114 transient_func_t = get_initializer());
115
116 template <typename... T>
117 auto_base_bundle(const captured_location_t&, quirk::config<T...>,
118 transient_func_t = get_initializer());
119
120 explicit auto_base_bundle(string_view_cref_t, scope::config = scope::get_default(),
121 bool report_at_exit = settings::destructor_report(),
122 transient_func_t = get_initializer());
123
124 explicit auto_base_bundle(const captured_location_t&,
125 scope::config = scope::get_default(),
126 bool report_at_exit = settings::destructor_report(),
127 transient_func_t = get_initializer());
128
129 explicit auto_base_bundle(size_t, scope::config = scope::get_default(),
130 bool report_at_exit = settings::destructor_report(),
131 transient_func_t = get_initializer());
132
133 explicit auto_base_bundle(component_type& tmp, scope::config = scope::get_default(),
134 bool report_at_exit = settings::destructor_report());
135
136 template <typename Arg, typename... Args>
138 transient_func_t, Arg&&, Args&&...);
139
140 template <typename Arg, typename... Args>
142 transient_func_t, Arg&&, Args&&...);
143
144 template <typename Arg, typename... Args>
146 Args&&...);
147
149
150 // copy and move
155
156 static constexpr std::size_t size() { return component_type::size(); }
157
158public:
159 // public member functions
160 component_type& get_component() { return m_temporary; }
161 const component_type& get_component() const { return m_temporary; }
162
163 /// implicit conversion to underlying component_type
164 operator component_type&() { return m_temporary; }
165 /// implicit conversion to const ref of underlying component_type
166 operator const component_type&() const { return m_temporary; }
167
168 /// query the number of (compile-time) fixed components
169 static constexpr auto fixed_count() { return component_type::fixed_count(); }
170 /// query the number of (run-time) optional components
171 static constexpr auto optional_count() { return component_type::optional_count(); }
172 /// count number of active components in an instance
173 auto count() { return (m_enabled) ? m_temporary.count() : 0; }
174 /// when chaining together operations, this enables executing a function inside the
175 /// chain
176 template <typename FuncT, typename... Args>
177 decltype(auto) execute(FuncT&& func, Args&&... args)
178 {
179 return mpl::execute(static_cast<this_type&>(*this),
180 std::forward<FuncT>(func)(std::forward<Args>(args)...));
181 }
182
183 /// push components into call-stack storage
184 template <typename... Args>
185 this_type& push(Args&&... args);
186
187 /// pop components off call-stack storage
188 template <typename... Args>
189 this_type& pop(Args&&... args);
190
191 /// execute a measurement
192 template <typename... Args>
193 this_type& measure(Args&&... args);
194
195 /// record some data
196 template <typename... Args>
197 this_type& record(Args&&... args);
198
199 /// execute a sample
200 template <typename... Args>
201 this_type& sample(Args&&... args);
202
203 /// invoke start member function on all components
204 template <typename... Args>
205 this_type& start(Args&&... args);
206
207 /// invoke stop member function on all components
208 template <typename... Args>
209 this_type& stop(Args&&... args);
210
211 /// invoke assemble member function on all components to determine if measurements can
212 /// be derived from other components in a bundle
213 template <typename... Args>
214 this_type& assemble(Args&&... args);
215
216 /// invoke derive member function on all components to extract measurements from other
217 /// components in the bundle
218 template <typename... Args>
219 this_type& derive(Args&&... args);
220
221 /// invoke mark member function on all components
222 template <typename... Args>
223 this_type& mark(Args&&... args);
224
225 /// invoke mark_begin member function on all components
226 template <typename... Args>
227 this_type& mark_begin(Args&&... args);
228
229 /// invoke mark_begin member function on all components
230 template <typename... Args>
231 this_type& mark_end(Args&&... args);
232
233 /// invoke store member function on all components
234 template <typename... Args>
235 this_type& store(Args&&... args);
236
237 /// invoke audit member function on all components
238 template <typename... Args>
239 this_type& audit(Args&&... args);
240
241 /// add secondary data
242 template <typename... Args>
243 this_type& add_secondary(Args&&... args);
244
245 /// reset the data
246 template <typename... Args>
247 this_type& reset(Args&&... args);
248
249 /// modify the scope of the push operation
250 template <typename... Args>
251 this_type& set_scope(Args&&... args);
252
253 /// set the key
254 template <typename... Args>
255 this_type& set_prefix(Args&&... args);
256
257 /// invoke the provided operation on all components
258 template <template <typename> class OpT, typename... Args>
259 this_type& invoke(Args&&... _args);
260
261 /// invoke get member function on all components to get their data
262 template <typename... Args>
263 auto get(Args&&... args) const
264 {
265 return m_temporary.get(std::forward<Args>(args)...);
266 }
267
268 /// invoke get member function on all components to get data labeled with component
269 /// name
270 template <typename... Args>
271 auto get_labeled(Args&&... args) const
272 {
273 return m_temporary.get_labeled(std::forward<Args>(args)...);
274 }
275
276 /// check whether enabled
277 bool enabled() const;
278
279 /// check whether reporting at exit
280 bool report_at_exit() const;
281
282 /// check whether storing data
283 bool store() const;
284
285 /// get the number of laps
286 int64_t laps() const;
287
288 /// get the key hash
289 uint64_t hash() const;
290
291 /// get the key
292 std::string key() const;
293
294 /// get tuple data
295 data_type& data();
296
297 /// get tuple data
298 const data_type& data() const;
299
300 /// write to stdout during destruction
301 this_type& report_at_exit(bool val);
302
303 /// update key
304 this_type& rekey(string_view_cref_t _key);
305
306 /// update key
307 this_type& rekey(captured_location_t _loc);
308
309 /// update key
310 this_type& rekey(uint64_t _hash);
311
312 /// returns a stack-object for calling stop
313 scope::transient_destructor get_scope_destructor();
314
315 /// returns a stack-object for calling some member functions when the scope is exited.
316 scope::transient_destructor get_scope_destructor(
317 utility::transient_function<void(this_type&)>);
318
319public:
320 template <typename Tp, typename... Args>
321 auto init(Args&&... args)
322 {
323 m_temporary.template init<Tp>(std::forward<Args>(args)...);
324 }
325
326 template <typename... Tp, typename... Args>
327 auto initialize(Args&&... args)
328 {
329 m_temporary.template initialize<Tp...>(std::forward<Args>(args)...);
330 }
331
332 template <typename... Tail>
333 void disable();
334
335 template <typename Tp, typename... Args>
336 decltype(auto) get(Args&&... args)
337 {
338 return m_temporary.template get<Tp>(std::forward<Args>(args)...);
339 }
340
341 template <typename Tp, typename... Args>
342 decltype(auto) get(Args&&... args) const
343 {
344 return m_temporary.template get<Tp>(std::forward<Args>(args)...);
345 }
346
347 void get(void*& ptr, size_t hash) const { m_temporary.get(ptr, hash); }
348
349 template <typename T>
351 -> decltype(std::declval<component_type>().template get_component<T>())
352 {
353 return m_temporary.template get_component<T>();
354 }
355
356 decltype(auto) get_data() const { return m_temporary.get_data(); }
357
359 {
360 m_temporary += rhs.m_temporary;
361 return static_cast<this_type&>(*this);
362 }
363
365 {
366 m_temporary -= rhs.m_temporary;
367 return static_cast<this_type&>(*this);
368 }
369
370 friend this_type operator+(const this_type& lhs, const this_type& rhs)
371 {
372 return this_type{ lhs } += rhs;
373 }
374
375 friend this_type operator-(const this_type& lhs, const this_type& rhs)
376 {
377 return this_type{ lhs } -= rhs;
378 }
379
380protected:
381 void internal_init(transient_func_t _init);
382
383 template <typename Arg, typename... Args>
384 void internal_init(transient_func_t _init, Arg&& _arg, Args&&... _args);
385
386protected:
387 bool m_enabled = true;
388 bool m_report_at_exit = false;
389 component_type* m_reference_object = nullptr;
391
392private:
393 this_type& get_this_type() { return static_cast<this_type&>(*this); }
394 this_type& get_this_type() const
395 {
396 return const_cast<this_type&>(static_cast<const this_type&>(*this));
397 }
398};
399//
400} // namespace tim
void get(void *&ptr, size_t hash) const
this_type & assemble(Args &&... args)
invoke assemble member function on all components to determine if measurements can be derived from ot...
this_type & start(Args &&... args)
invoke start member function on all components
this_type & store(Args &&... args)
invoke store member function on all components
typename base_type::component_type component_type
this_type & record(Args &&... args)
record some data
this_type & operator+=(const this_type &rhs)
typename component_type::data_type data_type
this_type & mark_end(Args &&... args)
invoke mark_begin member function on all components
decltype(auto) execute(FuncT &&func, Args &&... args)
when chaining together operations, this enables executing a function inside the chain
this_type & set_scope(Args &&... args)
modify the scope of the push operation
const component_type & get_component() const
this_type & push(Args &&... args)
push components into call-stack storage
this_type & operator-=(const this_type &rhs)
this_type & mark_begin(Args &&... args)
invoke mark_begin member function on all components
auto get(Args &&... args) const
invoke get member function on all components to get their data
typename component_type::bundle_type bundle_type
this_type & measure(Args &&... args)
execute a measurement
this_type & pop(Args &&... args)
pop components off call-stack storage
auto_base_bundle(string_view_cref_t, bool store, scope::config _scope, transient_func_t, Arg &&, Args &&...)
tim::variadic::impl::quirk_config< T, convert_t< BundleT, type_list<> >, U... > quirk_config
auto get_component() -> decltype(std::declval< component_type >().template get_component< T >())
this_type & audit(Args &&... args)
invoke audit member function on all components
this_type & reset(Args &&... args)
reset the data
typename component_type::sample_type sample_type
static constexpr auto optional_count()
query the number of (run-time) optional components
auto_base_bundle(auto_base_bundle &&)=default
typename component_type::tuple_type tuple_type
auto_base_bundle(const captured_location_t &, bool store, scope::config _scope, transient_func_t, Arg &&, Args &&...)
this_type & set_prefix(Args &&... args)
set the key
static constexpr auto fixed_count()
query the number of (compile-time) fixed components
this_type & invoke(Args &&... _args)
invoke the provided operation on all components
this_type & stop(Args &&... args)
invoke stop member function on all components
this_type & sample(Args &&... args)
execute a sample
auto_base_bundle & operator=(auto_base_bundle &&)=default
this_type & add_secondary(Args &&... args)
add secondary data
this_type & derive(Args &&... args)
invoke derive member function on all components to extract measurements from other components in the ...
auto count()
count number of active components in an instance
friend this_type operator-(const this_type &lhs, const this_type &rhs)
this_type & mark(Args &&... args)
invoke mark member function on all components
friend this_type operator+(const this_type &lhs, const this_type &rhs)
auto_base_bundle(size_t, bool store, scope::config _scope, transient_func_t, Arg &&, Args &&...)
auto_base_bundle & operator=(const auto_base_bundle &)=default
std::function< void(this_type &)> initializer_type
decltype(auto) get(Args &&... args) const
auto_base_bundle(const auto_base_bundle &)=default
typename component_type::captured_location_t captured_location_t
auto get_labeled(Args &&... args) const
invoke get member function on all components to get data labeled with component name
void store(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:564
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 >)
std::bitset< scope_count > data_type
Definition: types.hpp:399
A light-weight alternative to std::function. Pass any callback - including capturing lambdas - cheapl...
Definition: kokkosp.cpp:39
std::array< char *, 4 > _args
void initialize(CompList< CompTypes... > &obj, std::initializer_list< EnumT > components)
Definition: initialize.hpp:53
const std::string & string_view_cref_t
Definition: language.hpp:103
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
destructor_report
Definition: settings.cpp:1781
typename impl::convert< T, U >::type convert_t
Definition: types.hpp:855
Static polymorphic base class for automatic start/stop bundlers.
Definition: types.hpp:72
concept that specifies that a type is an API. APIs are used to designate different project implementa...
Definition: concepts.hpp:273
a variadic type which holds zero or more quirks that are passed to the constructor of a component bun...
Definition: quirks.hpp:39
this data type encodes the options of storage scope. The default is hierarchical (tree) scope....
Definition: types.hpp:453