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.
impl.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
34
35#include <cstddef>
36#include <functional>
37#include <string>
38#include <tuple>
39#include <utility>
40
41namespace tim
42{
43namespace variadic
44{
45//
46namespace impl
47{
48template <typename T>
49struct add_pointer_if_not
50{
51 using type = conditional_t<std::is_pointer<T>::value, T, std::add_pointer_t<T>>;
52};
53//
54template <typename... T>
55struct add_pointer_if_not<type_list<T...>>
56{
58};
59//
60} // namespace impl
61//
62template <typename T>
63using add_pointer_if_not_t = typename impl::add_pointer_if_not<T>::type;
64//
65template <typename... T>
67{
69
70 /// the set of types, unaltered, in a type_list
71 using type_list_type = type_list<T...>;
72
73 /// the set of types without any pointers
75
76 /// type list of the available types
78
79 /// the original bundle type
80 template <typename BundleT>
81 using this_type = convert_t<type_list<T...>, BundleT>;
82
83 /// the type after available_t<concat<...>>
84 template <typename BundleT>
86
87 /// conversion to equivalent wrapper requiring explicit start/stop
88 template <typename BundleT>
89 using component_type = convert_t<type_list<T...>, BundleT>;
90
91 /// conversion to equivalent wrapper which automatically starts/stops
92 template <typename BundleT>
94
95 /// the valid types to instantiate in a tuple
96 template <typename ApiT = TIMEMORY_API>
100 std::tuple<>>,
101 std::tuple<>>;
102};
103
104template <typename... T>
106{
108
109 /// the set of types, unaltered, in a type_list
110 using type_list_type = type_list<T...>;
111
112 /// the set of types without any pointers
114
115 /// type list of the available types
117
118 /// the original bundle type
119 template <typename BundleT>
121
122 /// the type after available_t<concat<...>>
123 template <typename BundleT>
125
126 /// conversion to equivalent wrapper requiring explicit start/stop
127 template <typename BundleT>
128 using component_type = convert_t<type_list<T...>, BundleT>;
129
130 /// conversion to equivalent wrapper which automatically starts/stops
131 template <typename BundleT>
133
134 /// the valid types to instantiate in a tuple
135 template <typename ApiT = TIMEMORY_API>
136 using data_type =
140 std::tuple<>>,
141 std::tuple<>>;
142};
143
144template <typename... T>
146{
148
149 /// the set of types, unaltered, in a type_list
150 using type_list_type = type_list<T...>;
151
152 /// the set of types without any pointers
154
155 /// type list of the available types
157
158 /// the original bundle type
159 template <typename BundleT>
161
162 /// the type after available_t<concat<...>>
163 template <typename BundleT>
164 using type = convert_t<type_list_t<T...>, BundleT>;
165
166 /// conversion to equivalent wrapper requiring explicit start/stop
167 template <typename BundleT>
168 using component_type = convert_t<type_list<T...>, BundleT>;
169
170 /// conversion to equivalent wrapper which automatically starts/stops
171 template <typename BundleT>
173
174 /// the valid types to instantiate in a tuple
175 template <typename ApiT = TIMEMORY_API>
179 std::tuple<>>,
180 std::tuple<>>;
181};
182//
183template <typename... T>
185{};
186
187template <typename... T>
189{};
190
191template <typename... T>
193{};
194//
195template <typename... T>
196struct heap_wrapper_types<std::tuple<T...>> : heap_wrapper_types<T...>
197{};
198
199template <typename... T>
200struct stack_wrapper_types<std::tuple<T...>> : stack_wrapper_types<T...>
201{};
202
203template <typename... T>
204struct mixed_wrapper_types<std::tuple<T...>> : mixed_wrapper_types<T...>
205{};
206//
207namespace impl
208{
209struct internal_tag
210{};
211
212template <typename... T>
213struct bundle;
214
215template <typename C, typename A, typename T>
216struct bundle_definitions;
217
218using EmptyT = std::tuple<>;
219
220template <typename U>
221using sample_type_t =
222 conditional_t<trait::sampler<U>::value, operation::sample<U>, EmptyT>;
223
224template <typename... T>
225struct bundle
226{
227 using tuple_type = std::tuple<T...>;
228 using reference_type = std::tuple<T...>;
229 using sample_type = std::tuple<sample_type_t<T>...>;
230 using print_type = std::tuple<operation::print<T>...>;
231};
232
233template <typename... T>
234struct bundle<std::tuple<T...>> : bundle<T...>
235{};
236
237template <typename... T>
238struct bundle<type_list<T...>> : bundle<T...>
239{};
240
241template <template <typename...> class CompL, template <typename...> class AutoL,
242 template <typename...> class DataL, typename... L, typename... T>
243struct bundle_definitions<CompL<L...>, AutoL<L...>, DataL<T...>>
244{
245 using component_type = CompL<T...>;
246 using auto_type = AutoL<T...>;
247};
248
249template <template <typename> class Op, typename TagT, typename... T>
250struct generic_operation;
251
252template <template <typename> class Op, typename... T>
253struct custom_operation;
254
255template <template <typename> class Op, typename TagT, typename... T>
256struct generic_operation
257{
258 using type =
259 std::tuple<operation::generic_operator<remove_pointer_t<T>,
260 Op<remove_pointer_t<T>>, TagT>...>;
261};
262
263template <template <typename> class Op, typename TagT, typename... T>
264struct generic_operation<Op, TagT, std::tuple<T...>> : generic_operation<Op, TagT, T...>
265{};
266
267template <template <typename> class Op, typename... T>
268struct custom_operation
269{
270 using type = std::tuple<Op<T>...>;
271};
272
273template <template <typename> class Op, typename... T>
274struct custom_operation<Op, std::tuple<T...>> : custom_operation<Op, T...>
275{};
276
277template <typename... U>
278struct quirk_config;
279
280template <typename T, typename... F, typename... U>
281struct quirk_config<T, type_list<F...>, U...>
282{
283 static constexpr bool value =
284 is_one_of<T, type_list<F..., U...>>::value ||
285 is_one_of<T, contains_one_of_t<quirk::is_config, concat<F..., U...>>>::value;
286};
287
288template <typename Tp, size_t N, size_t... Idx>
289auto
290to_tuple_pointer(std::array<Tp, N>& _data, std::index_sequence<Idx...>,
291 enable_if_t<!std::is_pointer<Tp>::value, int> = 0)
292{
293 return std::make_tuple(std::addressof(std::get<Idx>(_data))...);
294}
295
296template <typename Tp, size_t N, size_t... Idx>
297auto
298to_tuple_pointer(std::array<Tp, N>& _data, std::index_sequence<Idx...>,
299 enable_if_t<std::is_pointer<Tp>::value, int> = 0)
300{
301 return std::make_tuple(std::get<Idx>(_data)...);
302}
303
304TIMEMORY_INLINE
305bool
306global_enabled()
307{
308 static bool& _value = settings::enabled();
309 return _value;
310}
311
312//----------------------------------------------------------------------------------//
313// type is not explicitly listed so redirect to opaque search
314//
315template <typename ApiT = TIMEMORY_API, template <typename...> class TupleT,
316 typename... Types>
317void
318get(const TupleT<Types...>& m_data, void*& ptr, size_t _hash)
319{
320 // using data_type = type_list<Types...>;
321 // TIMEMORY_FOLD_EXPRESSION(
322 // operation::generic_operator<Types, operation::get<Types>, ApiT>{
323 // std::get<index_of<Types, data_type>::value>(m_data), ptr, _hash });
324
325 using get_type = std::tuple<operation::generic_operator<
326 decay_t<remove_pointer_t<Types>>,
327 operation::get<decay_t<remove_pointer_t<Types>>>, ApiT>...>;
328 mpl::apply<void>::access<get_type>(m_data, ptr, _hash);
329}
330
331//----------------------------------------------------------------------------------//
332// exact type available
333//
334template <typename U, typename ApiT = TIMEMORY_API, typename data_type,
335 typename T = decay_t<U>>
336decltype(auto)
337get(data_type&& m_data,
338 enable_if_t<is_one_of<T, decay_t<data_type>>::value && !std::is_pointer<T>::value,
339 int> = 0)
340{
341 return &(std::get<index_of<T, decay_t<data_type>>::value>(
342 std::forward<data_type>(m_data)));
343}
344
345//----------------------------------------------------------------------------------//
346// exact type available (pointer query)
347//
348template <typename U, typename ApiT = TIMEMORY_API, typename data_type,
349 typename T = decay_t<U>>
350decltype(auto)
351get(data_type&& m_data,
352 enable_if_t<is_one_of<T, decay_t<data_type>>::value && std::is_pointer<T>::value,
353 long> = 0)
354{
355 return std::get<index_of<T, decay_t<data_type>>::value>(
356 std::forward<data_type>(m_data));
357}
358
359//
360//----------------------------------------------------------------------------------//
361// type available with add_pointer
362//
363template <typename U, typename ApiT = TIMEMORY_API, typename data_type,
364 typename T = decay_t<U>>
365decltype(auto)
366get(data_type&& m_data, enable_if_t<is_one_of<T*, decay_t<data_type>>::value &&
367 !is_one_of<T, decay_t<data_type>>::value,
368 long> = 0)
369{
370 return std::get<index_of<T*, decay_t<data_type>>::value>(m_data);
371}
372
373//
374//----------------------------------------------------------------------------------//
375// type available with remove_pointer
376//
377template <typename U, typename ApiT = TIMEMORY_API, typename data_type,
378 typename T = decay_t<U>, typename R = remove_pointer_t<T>>
379decltype(auto)
380get(data_type&& m_data, enable_if_t<!is_one_of<T, decay_t<data_type>>::value &&
381 !is_one_of<T*, decay_t<data_type>>::value &&
382 is_one_of<R, decay_t<data_type>>::value,
383 int> = 0)
384{
385 return &std::get<index_of<R, decay_t<data_type>>::value>(m_data);
386}
387
388//
389//----------------------------------------------------------------------------------//
390/// type is not explicitly listed so redirect to opaque search
391///
392template <typename U, typename ApiT = TIMEMORY_API, typename data_type,
393 typename T = decay_t<U>, typename R = remove_pointer_t<T>>
394decltype(auto)
395get(data_type&& m_data, enable_if_t<!is_one_of<T, decay_t<data_type>>::value &&
396 !is_one_of<T*, decay_t<data_type>>::value &&
397 !is_one_of<R, decay_t<data_type>>::value,
398 int> = 0)
399{
400 void* ptr = nullptr;
401 get(std::forward<data_type>(m_data), ptr, typeid_hash<T>());
402 return static_cast<T*>(ptr);
403}
404
405//----------------------------------------------------------------------------------//
406/// this is a simple alternative to get<T>() when used from SFINAE in operation
407/// namespace which has a struct get also templated. Usage there can cause error
408/// with older compilers
409template <typename U, typename data_type, typename T = std::remove_pointer_t<decay_t<U>>>
410auto
411get_component(
412 data_type&& m_data,
413 enable_if_t<trait::is_available<T>::value && is_one_of<T, decay_t<data_type>>::value,
414 int> = 0)
415{
416 return get<T>(std::forward<data_type>(m_data));
417}
418
419template <typename U, typename data_type, typename T = std::remove_pointer_t<decay_t<U>>>
420auto
421get_component(
422 data_type&& m_data,
423 enable_if_t<trait::is_available<T>::value && is_one_of<T*, decay_t<data_type>>::value,
424 int> = 0)
425{
426 return get<T>(std::forward<data_type>(m_data));
427}
428
429/// returns a reference from a stack component instead of a pointer
430template <typename U, typename data_type, typename T = std::remove_pointer_t<decay_t<U>>>
431auto&
432get_reference(
433 data_type& m_data,
434 enable_if_t<trait::is_available<T>::value && is_one_of<T, decay_t<data_type>>::value,
435 int> = 0)
436{
437 return std::get<index_of<T, decay_t<data_type>>::value>(m_data);
438}
439
440/// returns a reference from a heap component instead of a pointer
441template <typename U, typename data_type, typename T = std::remove_pointer_t<decay_t<U>>>
442auto&
443get_reference(
444 data_type& m_data,
445 enable_if_t<trait::is_available<T>::value && is_one_of<T*, decay_t<data_type>>::value,
446 int> = 0)
447{
448 return std::get<index_of<T*, decay_t<data_type>>::value>(m_data);
449}
450
451} // namespace impl
452} // namespace variadic
453} // namespace tim
STL namespace.
typename auto_type< T >::type auto_type_t
Definition: concepts.hpp:581
impl::filter_true< concepts::is_quirk_type, T > non_quirk_t
Definition: available.hpp:310
impl::filter_true< concepts::is_placeholder, T > non_placeholder_t
Definition: available.hpp:313
std::bitset< scope_count > data_type
Definition: types.hpp:399
typename impl::add_pointer_if_not< T >::type add_pointer_if_not_t
Definition: impl.hpp:63
Definition: kokkosp.cpp:39
typename impl::concat< Types... >::type concat
Definition: types.hpp:707
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
convert_t< mpl::available_t< concat< T... > >, type_list<> > type_list_t
Definition: available.hpp:333
typename impl::is_one_of< Tp, Types > is_one_of
check if type is in expansion
Definition: types.hpp:777
typename contains_one_of< Predicate, Types >::type contains_one_of_t
Definition: types.hpp:786
auto get(const auto_bundle< Tag, Types... > &_obj)
typename std::conditional< B, Lhs, Rhs >::type conditional_t
Definition: types.hpp:197
typename impl::convert< T, U >::type convert_t
Definition: types.hpp:855
lightweight tuple-alternative for meta-programming logic
Definition: types.hpp:233
Declare the operations types.
trait that signifies that an implementation for the component is available. When this is set to false...
Definition: types.hpp:355
convert_t< available_type, BundleT > type
the type after available_t<concat<...>>
Definition: impl.hpp:85
conditional_t< trait::is_available< ApiT >::value, convert_t< add_pointer_if_not_t< mpl::non_placeholder_t< mpl::non_quirk_t< type_list_t< T... > > > >, std::tuple<> >, std::tuple<> > data_type
the valid types to instantiate in a tuple
Definition: impl.hpp:101
convert_t< type_list< T... >, BundleT > this_type
the original bundle type
Definition: impl.hpp:81
convert_t< type_list< T... >, BundleT > component_type
conversion to equivalent wrapper requiring explicit start/stop
Definition: impl.hpp:89
type_list_t< reference_type > available_type
type list of the available types
Definition: impl.hpp:77
TIMEMORY_DELETED_OBJECT(heap_wrapper_types) using type_list_type
the set of types, unaltered, in a type_list
concepts::auto_type_t< convert_t< type_list_type, BundleT > > auto_type
conversion to equivalent wrapper which automatically starts/stops
Definition: impl.hpp:93
concepts::auto_type_t< convert_t< type_list_type, BundleT > > auto_type
conversion to equivalent wrapper which automatically starts/stops
Definition: impl.hpp:172
convert_t< type_list_type, BundleT > this_type
the original bundle type
Definition: impl.hpp:160
convert_t< type_list< T... >, BundleT > component_type
conversion to equivalent wrapper requiring explicit start/stop
Definition: impl.hpp:168
convert_t< type_list_t< T... >, BundleT > type
the type after available_t<concat<...>>
Definition: impl.hpp:164
conditional_t< trait::is_available< ApiT >::value, convert_t< mpl::non_placeholder_t< mpl::non_quirk_t< type_list_t< T... > > >, std::tuple<> >, std::tuple<> > data_type
the valid types to instantiate in a tuple
Definition: impl.hpp:180
type_list_t< std::remove_pointer_t< T >... > available_type
type list of the available types
Definition: impl.hpp:156
TIMEMORY_DELETED_OBJECT(mixed_wrapper_types) using type_list_type
the set of types, unaltered, in a type_list
type_list_t< reference_type > available_type
type list of the available types
Definition: impl.hpp:116
convert_t< type_list< T... >, BundleT > component_type
conversion to equivalent wrapper requiring explicit start/stop
Definition: impl.hpp:128
conditional_t< trait::is_available< ApiT >::value, convert_t< mpl::non_placeholder_t< mpl::non_quirk_t< type_list_t< std::remove_pointer_t< T >... > > >, std::tuple<> >, std::tuple<> > data_type
the valid types to instantiate in a tuple
Definition: impl.hpp:141
concepts::auto_type_t< convert_t< type_list_type, BundleT > > auto_type
conversion to equivalent wrapper which automatically starts/stops
Definition: impl.hpp:132
TIMEMORY_DELETED_OBJECT(stack_wrapper_types) using type_list_type
the set of types, unaltered, in a type_list
convert_t< type_list_type, BundleT > this_type
the original bundle type
Definition: impl.hpp:120
convert_t< available_type, BundleT > type
the type after available_t<concat<...>>
Definition: impl.hpp:124
type_list
Definition: types.hpp:211