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.
types.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/** \file timemory/utility/types.hpp
26 * \headerfile timemory/utility/types.hpp "timemory/utility/types.hpp"
27 * Declaration of types for utility directory
28 *
29 */
30
31#pragma once
32
39
40#include <array>
41#include <bitset>
42#include <functional>
43#include <initializer_list>
44#include <memory>
45#include <ostream>
46#include <sstream>
47#include <string>
48#include <type_traits>
49
50//======================================================================================//
51//
52#if !defined(TIMEMORY_FOLD_EXPRESSION)
53# if defined(CXX17)
54# define TIMEMORY_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
55# else
56# define TIMEMORY_FOLD_EXPRESSION(...) \
57 ::tim::consume_parameters(::std::initializer_list<int>{ (__VA_ARGS__, 0)... })
58# endif
59#endif
60
61//======================================================================================//
62//
63#if !defined(TIMEMORY_FOLD_EXPANSION)
64# define TIMEMORY_FOLD_EXPANSION(TYPE, SIZE, ...) \
65 std::array<TYPE, SIZE>({ (::tim::consume_parameters(), __VA_ARGS__)... });
66#endif
67
68//======================================================================================//
69//
70#if !defined(TIMEMORY_RETURN_FOLD_EXPRESSION)
71# define TIMEMORY_RETURN_FOLD_EXPRESSION(...) \
72 ::std::make_tuple((::tim::consume_parameters(), __VA_ARGS__)...)
73#endif
74
75//======================================================================================//
76//
77#if !defined(TIMEMORY_DECLARE_EXTERN_TEMPLATE)
78# define TIMEMORY_DECLARE_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
79#endif
80
81//======================================================================================//
82//
83#if !defined(TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE)
84# define TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE(...) template __VA_ARGS__;
85#endif
86
87//======================================================================================//
88//
89#if !defined(TIMEMORY_ESC)
90# define TIMEMORY_ESC(...) __VA_ARGS__
91#endif
92
93//======================================================================================//
94//
95#if !defined(TIMEMORY_DELETED_OBJECT)
96# define TIMEMORY_DELETED_OBJECT(NAME) \
97 NAME() = delete; \
98 NAME(const NAME&) = delete; \
99 NAME(NAME&&) = delete; \
100 NAME& operator=(const NAME&) = delete; \
101 NAME& operator=(NAME&&) = delete;
102#endif
103
104//======================================================================================//
105//
106#if !defined(TIMEMORY_DELETE_COPY_MOVE_OBJECT)
107# define TIMEMORY_DELETE_COPY_MOVE_OBJECT(NAME) \
108 NAME(const NAME&) = delete; \
109 NAME(NAME&&) = delete; \
110 NAME& operator=(const NAME&) = delete; \
111 NAME& operator=(NAME&&) = delete;
112#endif
113
114//======================================================================================//
115//
116#if !defined(TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT)
117# define TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT(NAME) \
118 NAME(const NAME&) = delete; \
119 NAME(NAME&&) noexcept = default; \
120 NAME& operator=(const NAME&) = delete; \
121 NAME& operator=(NAME&&) noexcept = default;
122#endif
123
124//======================================================================================//
125//
126#if !defined(TIMEMORY_DEFAULT_OBJECT)
127# define TIMEMORY_DEFAULT_OBJECT(NAME) \
128 TIMEMORY_HOST_DEVICE_FUNCTION NAME() = default; \
129 NAME(const NAME&) = default; \
130 NAME(NAME&&) noexcept = default; \
131 NAME& operator=(const NAME&) = default; \
132 NAME& operator=(NAME&&) noexcept = default;
133#endif
134
135//======================================================================================//
136//
137#if !defined(TIMEMORY_EXCEPTION)
138# define TIMEMORY_EXCEPTION(...) \
139 { \
140 std::stringstream _errmsg; \
141 _errmsg << __VA_ARGS__; \
142 perror(_errmsg.str().c_str()); \
143 std::cerr << _errmsg.str() << std::endl; \
144 std::exit(EXIT_FAILURE); \
145 }
146#endif
147
148//======================================================================================//
149//
150#if !defined(TIMEMORY_TESTING_EXCEPTION) && defined(TIMEMORY_INTERNAL_TESTING)
151# define TIMEMORY_TESTING_EXCEPTION(...) \
152 { \
153 TIMEMORY_EXCEPTION(__VA_ARGS__) \
154 }
155#elif !defined(TIMEMORY_TESTING_EXCEPTION)
156# define TIMEMORY_TESTING_EXCEPTION(...) \
157 {}
158#endif
159
160//======================================================================================//
161//
162#if !defined(TIMEMORY_TUPLE_ACCESSOR)
163# define TIMEMORY_TUPLE_ACCESSOR(INDEX, TUPLE, NAME) \
164 auto& NAME() { return std::get<INDEX>(TUPLE); } \
165 const auto& NAME() const { return std::get<INDEX>(TUPLE); }
166#endif
167
168//======================================================================================//
169//
170namespace tim
171{
172/// Alias template make_integer_sequence
173template <typename Tp, Tp Num>
174using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
175//
176/// Alias template index_sequence
177template <size_t... Idx>
178using index_sequence = std::integer_sequence<size_t, Idx...>;
179//
180/// Alias template make_index_sequence
181template <size_t Num>
182using make_index_sequence = std::make_integer_sequence<size_t, Num>;
183//
184/// Alias template index_sequence_for
185template <typename... Types>
187//
188/// Alias template for enable_if
189template <bool B, typename T = int>
190using enable_if_t = typename std::enable_if<B, T>::type;
191//
192/// Alias template for decay
193template <typename T>
194using decay_t = typename std::decay<T>::type;
195//
196template <bool B, typename Lhs, typename Rhs>
197using conditional_t = typename std::conditional<B, Lhs, Rhs>::type;
198//
199template <typename T>
200using remove_cv_t = typename std::remove_cv<T>::type;
201//
202template <typename T>
203using remove_const_t = typename std::remove_const<T>::type;
204//
205template <int N>
206using priority_constant = std::integral_constant<int, N>;
207//
208//--------------------------------------------------------------------------------------//
209//
210template <typename T>
212{
213 using type = T;
214};
215//
216template <typename T>
218//
219//--------------------------------------------------------------------------------------//
220//
221/// \struct tim::null_type
222/// \brief this is a placeholder type for optional type-traits. It is used as the default
223/// type for the type-traits to signify there is no specialization.
225{};
226//
227//--------------------------------------------------------------------------------------//
228//
229/// \struct tim::type_list
230/// \brief lightweight tuple-alternative for meta-programming logic
231template <typename... Tp>
233{};
234//
235//--------------------------------------------------------------------------------------//
236//
237/// \struct tim::type_list_element
238/// \brief Variant of `std::tuple_element` for \ref tim::type_list
239template <size_t Idx, typename Tp>
240struct type_list_element;
241
242namespace internal
243{
244template <size_t Idx, size_t TargIdx, typename... Tail>
245struct type_list_element;
246
247template <size_t Idx, size_t TargIdx>
248struct type_list_element<Idx, TargIdx>
249{
250 using type = tim::null_type;
251 // TargIdx will be equal to Idx + 1 in second half of conditional statement
252 // below. If the second half of that conditional statement is entered, the
253 // following static_assert will be true
254 static_assert(TargIdx < Idx + 2, "Error! Index exceeded size of of type_list");
255};
256
257template <size_t Idx, size_t TargIdx, typename Tp, typename... Tail>
258struct type_list_element<Idx, TargIdx, Tp, Tail...>
259{
260 using type =
261 conditional_t<Idx == TargIdx, Tp,
262 typename type_list_element<Idx + 1, TargIdx, Tail...>::type>;
263};
264} // namespace internal
265
266template <size_t Idx, typename... Types>
267struct type_list_element<Idx, type_list<Types...>>
268{
269 using type = typename internal::type_list_element<0, Idx, Types...>::type;
270};
271
272template <size_t Idx, typename Tp>
273using type_list_element_t = typename type_list_element<Idx, Tp>::type;
274//
275//--------------------------------------------------------------------------------------//
276//
277/// \fn tim::consume_parameters
278/// \brief use this function to get rid of "unused parameter" warnings
279template <typename... ArgsT>
280TIMEMORY_ALWAYS_INLINE void
281consume_parameters(ArgsT&&...) TIMEMORY_HIDDEN TIMEMORY_NEVER_INSTRUMENT;
282//
283template <typename... ArgsT>
284void
286{}
287//
288//--------------------------------------------------------------------------------------//
289//
290template <typename Tp, typename DeleterT, typename Tag>
291class singleton;
292//
293//--------------------------------------------------------------------------------------//
294//
295namespace cupti
296{
297struct result;
298}
299//
300//--------------------------------------------------------------------------------------//
301//
302namespace crtp
303{
304//
305//--------------------------------------------------------------------------------------//
306//
307/// \struct tim::crtp::base
308/// \brief a generic type for prioritizing a function call to the base class over
309/// derived functions, e.g. void start(crtp::base, Args&&... args) { start(args...); }
310struct base
311{};
312//
313//--------------------------------------------------------------------------------------//
314//
315} // namespace crtp
316//
317//--------------------------------------------------------------------------------------//
318//
319namespace mpl
320{
321//
322//--------------------------------------------------------------------------------------//
323//
324/// \struct tim::mpl::lightweight
325/// \brief a generic type for indicating that function call or constructor should be
326/// as lightweight as possible.
328{};
329//
330//--------------------------------------------------------------------------------------//
331//
332template <typename... Tp>
334{};
335//
336template <typename... Tp>
338{};
339//
340//--------------------------------------------------------------------------------------//
341//
342} // namespace mpl
343//
344//--------------------------------------------------------------------------------------//
345//
346namespace scope
347{
348//
349//--------------------------------------------------------------------------------------//
350//
351/// \struct tim::scope::tree
352/// \brief Dummy struct to designates tree (hierarchical) storage. This scope (default)
353/// maintains nesting in the call-graph storage. In this scoping mode, the results
354/// will be separated from each other based on the identifier AND the current number
355/// of component instances in a "start" region. E.g. for two components with the
356/// same identifiers where the first calls start, then the second calls start then
357/// the second will be at a depth of +1 relative to the first (i.e. a child of the first).
358struct tree : std::integral_constant<int, 2>
359{};
360//
361//--------------------------------------------------------------------------------------//
362//
363/// \struct tim::scope::flat
364/// \brief Dummy struct to designates flat (no hierarchy) storage.
365/// When flat scoping is globally enabled, all entries to the call-graph storage at
366/// entered at a depth of zero. Thus, if you want a report of all the function calls
367/// and their total values for each identifier, flat scoping should be globally enabled.
368/// This can be combined with timeline scoping to produce results where every measurement
369/// is its own call-graph entry at a depth of zero (produces a large amount of data).
370/// Flat-scoping can be enabled at the component bundler level also, there are two
371/// ways to do this: (1) to enable flat-scoping for all instances of the bundle, add \ref
372/// tim::quirk::flat_scope to the template parameters of the bundler; (2) to enable
373/// flat-scoping for specific bundler instances, pass \code{.cpp}
374/// tim::quirk::config<tim::quirk::flat_scope, ...>{} \endcode as the second argument to
375/// the constructor of the bundle.
376struct flat : std::integral_constant<int, 0>
377{};
378//
379//--------------------------------------------------------------------------------------//
380//
381/// \struct tim::scope::timeline
382/// \brief Dummy struct to designates timeline (hierarchical, non-duplicated) storage.
383/// It is meaningless by itself and should be combined with \ref tim::scope::tree or
384/// \ref tim::scope::flat. A tree timeline has all the hierarchy properties of the
385/// tree scope but entries at the same depth with the same identifiers are separated
386/// entries in the resuls.
387/// Timeline-scoping can be enabled at the component bundler level also, there are two
388/// ways to do this: (1) to enable timeline-scoping for all instances of the bundle, add
389/// \ref tim::quirk::timeline_scope to the template parameters of the bundler; (2) to
390/// enable timeline-scoping for specific bundler instances, pass \code{.cpp}
391/// tim::quirk::config<tim::quirk::timeline_scope, ...>{} \endcode as the second argument
392/// to the constructor of the bundle.
393struct timeline : std::integral_constant<int, 1>
394{};
395//
396//--------------------------------------------------------------------------------------//
397//
398static constexpr size_t scope_count = 3;
399using data_type = std::bitset<scope_count>;
400using input_type = std::array<bool, scope_count>;
401//
402//--------------------------------------------------------------------------------------//
403//
405get_fields() TIMEMORY_VISIBILITY("default");
406//
407inline input_type&
409{
410 static input_type _instance{ { false, false, false } };
411 return _instance;
412}
413//
414//--------------------------------------------------------------------------------------//
415//
416template <typename Arg, size_t... Idx>
417static TIMEMORY_INLINE auto
418generate(Arg&& arg, index_sequence<Idx...>)
419{
420 static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
421 data_type ret{};
422 TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, arg[Idx]));
423 return ret;
424}
425//
426//--------------------------------------------------------------------------------------//
427//
428template <size_t... Idx>
429static TIMEMORY_INLINE auto
430either(data_type ret, data_type arg, index_sequence<Idx...>)
431{
432 static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
433 TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, ret.test(Idx) || arg.test(Idx)));
434 return ret;
435}
436//
437//--------------------------------------------------------------------------------------//
438//
439static TIMEMORY_INLINE auto
440get_default_bitset() -> data_type
441{
442 return generate(get_fields(), make_index_sequence<scope_count>{});
443}
444//
445//--------------------------------------------------------------------------------------//
446/// \struct tim::scope::config
447/// \brief this data type encodes the options of storage scope. The default is
448/// hierarchical (tree) scope. Specification of flat scope overrides the hierarchy
449/// scope, e.g. you cannot have a hierarchical flat scope. The timeline scope
450/// is meaningless should a specification of tree or flat, thus the valid combinations
451/// are: tree, flat, tree + timeline, flat + timeline.
452struct config : public data_type
453{
455 : data_type(get_default_bitset())
456 {}
457
458 explicit config(const data_type& obj)
459 : data_type(obj)
460 {}
461
462 explicit config(data_type&& obj) noexcept
463 : data_type(std::forward<data_type>(obj))
464 {}
465
466 explicit config(bool _flat)
467 : data_type(generate(input_type{ { _flat, false, false } },
469 {}
470
471 explicit config(bool _flat, bool _timeline)
472 : data_type(generate(input_type{ { _flat, _timeline, false } },
474 {}
475
476 explicit config(bool _flat, bool _timeline, bool _tree)
477 : data_type(generate(input_type{ { _flat, _timeline, _tree } },
479 {}
480
483 {}
484
487 {}
488
491 {}
492
493 template <typename Arg, typename... Args,
494 std::enable_if_t<(std::is_same<Arg, tree>::value ||
495 std::is_same<Arg, flat>::value ||
496 std::is_same<Arg, timeline>::value),
497 int> = 0>
498 explicit config(Arg&& arg, Args&&... args)
499 {
500 *this += std::forward<Arg>(arg);
501 TIMEMORY_FOLD_EXPRESSION(*this += std::forward<Args>(args));
502 }
503
504 ~config() = default;
505 config(const config&) = default;
506 config(config&&) noexcept = default;
507 config& operator=(const config&) = default;
508 config& operator=(config&&) noexcept = default;
509
510 config& operator=(const data_type& rhs)
511 {
512 if(this != &rhs)
513 data_type::operator=(rhs);
514 return *this;
515 }
516
517 config& operator=(data_type&& rhs) noexcept
518 {
519 if(this != &rhs)
520 data_type::operator=(std::forward<data_type>(rhs));
521 return *this;
522 }
523
524 template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
525 std::is_same<T, flat>::value ||
526 std::is_same<T, timeline>::value),
527 int> = 0>
529 {
530 this->data_type::set(T::value, true);
531 return *this;
532 }
533
534 using data_type::set;
535
536 template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
537 std::is_same<T, flat>::value ||
538 std::is_same<T, timeline>::value),
539 int> = 0>
540 config& set(bool val = true)
541 {
542 this->data_type::set(T::value, val);
543 return *this;
544 }
545
546 TIMEMORY_NODISCARD bool is_flat() const { return this->test(flat::value); }
547 TIMEMORY_NODISCARD bool is_timeline() const { return this->test(timeline::value); }
548 // "tree" is default behavior so it returns true if nothing is set but gives
549 // priority to the flat setting
550 TIMEMORY_NODISCARD bool is_tree() const
551 {
552 return this->none() || (this->test(tree::value) && !this->test(flat::value));
553 }
554 TIMEMORY_NODISCARD bool is_flat_timeline() const
555 {
556 return (is_flat() && is_timeline());
557 }
558 TIMEMORY_NODISCARD bool is_tree_timeline() const
559 {
560 return (is_tree() && is_timeline());
561 }
562
563 template <bool ForceFlatT>
564 TIMEMORY_NODISCARD bool is_flat() const
565 {
566 return (ForceFlatT) ? true : this->test(flat::value);
567 }
568
569 template <bool ForceTreeT, bool ForceTimeT>
570 TIMEMORY_NODISCARD bool is_tree() const
571 {
572 return (ForceTreeT)
573 ? true
574 : ((ForceTimeT) ? false
575 : (this->none() || (this->test(tree::value) &&
576 !this->test(flat::value))));
577 }
578
579 friend std::ostream& operator<<(std::ostream& os, const config& obj)
580 {
581 std::stringstream ss;
582 ss << std::boolalpha << "tree: " << obj.is_tree() << ", flat: " << obj.is_flat()
583 << ", timeline: " << obj.is_timeline()
584 << ". Values: flat::value = " << obj.test(flat::value)
585 << ", timeline::value = " << obj.test(timeline::value)
586 << ", tree::value = " << obj.test(tree::value);
587 os << ss.str();
588 return os;
589 }
590
591 template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
592 typename ForceTimeT = false_type>
593 uint64_t compute_depth(uint64_t _current)
594 {
595 static_assert(!(ForceTreeT::value && ForceFlatT::value),
596 "Error! Type cannot enforce tree-based call-stack depth storage "
597 "and flat call-stack depth storage simulatenously");
598 // flat: always at depth of 1
599 // tree: features nesting
600 // timeline: features nesting if not flat and depth of 1 if flat
601 if(ForceFlatT::value || is_flat())
602 {
603 // flat + timeline will be differentiated via compute_hash
604 // flat + tree is invalid and flat takes precedence
605 // printf("compute_depth is flat at %i\n", (int) _current);
606 return 1;
607 }
608 // if not flat, return the nested depth and compute_hash will account
609 // for whether the entry is a duplicate or not
610 // printf("compute_depth is tree or timeline at %i\n", (int) _current);
611 return _current + 1;
612 }
613
614 template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
615 typename ForceTimeT = false_type>
616 uint64_t compute_hash(uint64_t _id, uint64_t _depth, uint64_t& _counter)
617 {
618 // flat/tree: always compute the same hash for a given depth and key
619 // timeline: uses a counter to differentiate idential hashes occurring at diff
620 // time points.
621 // below is a fall-through (i.e. not an if-else) bc either tree or flat can be
622 // combined with timeline but in the case of tree + flat, flat will take
623 // precedence.
624 if(is_tree<ForceTreeT::value, ForceTimeT::value>() ||
625 is_flat<ForceFlatT::value>())
626 {
627 _id = get_combined_hash_id(_id, _depth);
628 }
629 if(ForceTimeT::value || is_timeline())
630 {
631 _id = get_combined_hash_id(_id, _counter++);
632 }
633 return _id;
634 }
635};
636//
637//--------------------------------------------------------------------------------------//
638// clang-format off
639static TIMEMORY_INLINE config
640get_default() TIMEMORY_HOT;
641TIMEMORY_INLINE config
642operator+(config _lhs, tree) TIMEMORY_HOT;
643TIMEMORY_INLINE config
644operator+(config _lhs, flat) TIMEMORY_HOT;
645TIMEMORY_INLINE config
646operator+(config _lhs, timeline) TIMEMORY_HOT;
647TIMEMORY_INLINE config
648operator+(config _lhs, config _rhs) TIMEMORY_HOT;
649// clang-format on
650//--------------------------------------------------------------------------------------//
651//
652static TIMEMORY_INLINE auto
653get_default() -> config
654{
655 return config{ get_default_bitset() };
656}
657//
658//--------------------------------------------------------------------------------------//
659//
660TIMEMORY_INLINE auto
662{
663 _lhs.set(tree::value, true);
664 return _lhs;
665}
666//
667//--------------------------------------------------------------------------------------//
668//
669TIMEMORY_INLINE auto
671{
672 _lhs.set(flat::value, true);
673 return _lhs;
674}
675//
676//--------------------------------------------------------------------------------------//
677//
678TIMEMORY_INLINE auto
680{
681 _lhs.set(timeline::value, true);
682 return _lhs;
683}
684//
685//--------------------------------------------------------------------------------------//
686//
687TIMEMORY_INLINE auto
689{
690 return config{ either(_lhs, _rhs, make_index_sequence<scope_count>{}) };
691}
692//
693//--------------------------------------------------------------------------------------//
694//
695/// \struct tim::scope::destructor
696/// \brief provides an object which can be returned from functions that will execute
697/// the lambda provided during construction when it is destroyed
698///
700{
701 template <typename FuncT>
702 destructor(FuncT&& _func)
703 : m_functor(std::forward<FuncT>(_func))
704 {}
705
706 // delete copy operations
707 destructor(const destructor&) = delete;
708 destructor& operator=(const destructor&) = delete;
709
710 // allow move operations
711 destructor(destructor&& rhs) noexcept
712 : m_functor(std::move(rhs.m_functor))
713 {
714 rhs.m_functor = []() {};
715 }
716
718 {
719 if(this != &rhs)
720 {
721 m_functor = std::move(rhs.m_functor);
722 rhs.m_functor = []() {};
723 }
724 return *this;
725 }
726
727 ~destructor() { m_functor(); }
728
729private:
730 std::function<void()> m_functor = []() {};
731};
732//
733//--------------------------------------------------------------------------------------//
734//
735} // namespace scope
736//
737//--------------------------------------------------------------------------------------//
738//
739namespace lifetime
740{
741//
742//--------------------------------------------------------------------------------------//
743//
744/// \struct tim::lifetime::scoped
745/// \brief Dummy struct for meta-programming to designate that a component activates
746/// it's features at the first start() invocation and deactivates it's features when
747/// all instances that called start() have called stop(). Thus, the component's
748/// features are dependent on at least one component instance existing in memory
749/// (excluding the instances in the call-graph, which never call start/stop)
750///
751struct scoped
752{};
753//
754//--------------------------------------------------------------------------------------//
755//
756/// \struct tim::lifetime::persistent
757/// \brief Dummy struct for meta-programming to designate that a component activates its
758/// features in {global,thread}_init and deactivates it's features in
759/// {global,thead}_finalize
760///
762{};
763//
764//--------------------------------------------------------------------------------------//
765//
766} // namespace lifetime
767//
768//--------------------------------------------------------------------------------------//
769//
770namespace audit
771{
772//
773//--------------------------------------------------------------------------------------//
774//
775/// \struct tim::audit::incoming
776/// \brief Used by component audit member function to designate the
777/// parameters being passed are incoming (e.g. before a gotcha wrappee is invoked)
778///
780{};
781//
782//--------------------------------------------------------------------------------------//
783//
784/// \struct tim::audit::outgoing
785/// \brief Used by component audit member function to designate the
786/// parameters being passed are outgoing (e.g. the return value from a gotcha wrappee)
787///
788// audit the return type
790{};
791//
792//--------------------------------------------------------------------------------------//
793//
794} // namespace audit
795
796//--------------------------------------------------------------------------------------//
797
798} // namespace tim
799
800namespace std
801{
802template <size_t Idx, typename... Types>
803struct tuple_element<Idx, tim::type_list<Types...>>
804{
805 using type = typename tim::type_list_element<Idx, tim::type_list<Types...>>::type;
806};
807} // namespace std
808
809//--------------------------------------------------------------------------------------//
810
811namespace tim
812{
813namespace cereal
814{
815namespace detail
816{
817template <typename Tp>
818struct StaticVersion;
819} // namespace detail
820} // namespace cereal
821} // namespace tim
822
823//--------------------------------------------------------------------------------------//
824
825#if !defined(TIMEMORY_SET_CLASS_VERSION)
826# define TIMEMORY_SET_CLASS_VERSION(VERSION_NUMBER, ...) \
827 namespace tim \
828 { \
829 namespace cereal \
830 { \
831 namespace detail \
832 { \
833 template <> \
834 struct StaticVersion<__VA_ARGS__> \
835 { \
836 static constexpr std::uint32_t version = VERSION_NUMBER; \
837 }; \
838 } \
839 } \
840 }
841#endif
842
843#if !defined(TIMEMORY_GET_CLASS_VERSION)
844# define TIMEMORY_GET_CLASS_VERSION(...) \
845 ::tim::cereal::detail::StaticVersion<__VA_ARGS__>::version
846#endif
STL namespace.
a generic type for prioritizing a function call to the base class over derived functions,...
Definition: types.hpp:311
return false
Definition: definition.hpp:326
hash_value_t get_combined_hash_id(hash_value_t _lhs, Tp &&_rhs)
Definition: types.hpp:170
void audit(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:939
Dummy struct for meta-programming to designate that a component activates it's features at the first ...
Definition: types.hpp:752
Dummy struct for meta-programming to designate that a component activates its features in {global,...
Definition: types.hpp:762
a generic type for indicating that function call or constructor should be as lightweight as possible.
Definition: types.hpp:328
input_type & get_fields()
Definition: types.hpp:408
config operator+(config _lhs, config _rhs)
Definition: types.hpp:688
std::array< bool, scope_count > input_type
Definition: types.hpp:400
std::bitset< scope_count > data_type
Definition: types.hpp:399
Definition: kokkosp.cpp:39
typename std::remove_cv< T >::type remove_cv_t
Definition: types.hpp:200
std::make_integer_sequence< size_t, Num > make_index_sequence
Alias template make_index_sequence.
Definition: types.hpp:182
std::integral_constant< int, N > priority_constant
Definition: types.hpp:206
std::make_integer_sequence< Tp, Num > make_integer_sequence
Alias template make_integer_sequence.
Definition: types.hpp:174
typename std::remove_const< T >::type remove_const_t
Definition: types.hpp:203
typename type_list_element< Idx, Tp >::type type_list_element_t
Definition: types.hpp:273
typename std::decay< T >::type decay_t
Alias template for decay.
Definition: types.hpp:194
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
typename identity< T >::type identity_t
Definition: types.hpp:217
const std::string std::ostream * os
std::make_index_sequence< sizeof...(Types)> index_sequence_for
Alias template index_sequence_for.
Definition: types.hpp:186
typename std::conditional< B, Lhs, Rhs >::type conditional_t
Definition: types.hpp:197
std::integer_sequence< size_t, Idx... > index_sequence
Alias template index_sequence.
Definition: types.hpp:178
void consume_parameters(ArgsT &&...)
Definition: types.hpp:285
lightweight tuple-alternative for meta-programming logic
Definition: types.hpp:233
Used by component audit member function to designate the parameters being passed are incoming (e....
Definition: types.hpp:780
Used by component audit member function to designate the parameters being passed are outgoing (e....
Definition: types.hpp:790
this is a placeholder type for optional type-traits. It is used as the default type for the type-trai...
Definition: types.hpp:225
this data type encodes the options of storage scope. The default is hierarchical (tree) scope....
Definition: types.hpp:453
config(Arg &&arg, Args &&... args)
Definition: types.hpp:498
friend std::ostream & operator<<(std::ostream &os, const config &obj)
Definition: types.hpp:579
config(data_type &&obj) noexcept
Definition: types.hpp:462
config(const config &)=default
bool is_flat() const
Definition: types.hpp:564
config(config &&) noexcept=default
config & operator=(data_type &&rhs) noexcept
Definition: types.hpp:517
config & set(bool val=true)
Definition: types.hpp:540
bool is_tree() const
Definition: types.hpp:570
uint64_t compute_depth(uint64_t _current)
Definition: types.hpp:593
config & operator+=(T)
Definition: types.hpp:528
config(timeline)
Definition: types.hpp:489
bool is_tree_timeline() const
Definition: types.hpp:558
bool is_flat_timeline() const
Definition: types.hpp:554
config(bool _flat, bool _timeline, bool _tree)
Definition: types.hpp:476
config(bool _flat)
Definition: types.hpp:466
bool is_flat() const
Definition: types.hpp:546
bool is_timeline() const
Definition: types.hpp:547
uint64_t compute_hash(uint64_t _id, uint64_t _depth, uint64_t &_counter)
Definition: types.hpp:616
bool is_tree() const
Definition: types.hpp:550
config(bool _flat, bool _timeline)
Definition: types.hpp:471
config(const data_type &obj)
Definition: types.hpp:458
provides an object which can be returned from functions that will execute the lambda provided during ...
Definition: types.hpp:700
destructor & operator=(destructor &&rhs) noexcept
Definition: types.hpp:717
destructor(destructor &&rhs) noexcept
Definition: types.hpp:711
destructor(const destructor &)=delete
destructor & operator=(const destructor &)=delete
destructor(FuncT &&_func)
Definition: types.hpp:702
Dummy struct to designates flat (no hierarchy) storage. When flat scoping is globally enabled,...
Definition: types.hpp:377
Dummy struct to designates timeline (hierarchical, non-duplicated) storage. It is meaningless by itse...
Definition: types.hpp:394
Dummy struct to designates tree (hierarchical) storage. This scope (default) maintains nesting in the...
Definition: types.hpp:359
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:56
typename typename typename
Definition: types.hpp:226
type_list
Definition: types.hpp:211