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.
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 
33 #include "timemory/compat/macros.h"
34 #include "timemory/hash/types.hpp"
36 #include "timemory/macros/os.hpp"
38 
39 #include <array>
40 #include <bitset>
41 #include <functional>
42 #include <initializer_list>
43 #include <memory>
44 #include <ostream>
45 #include <sstream>
46 #include <string>
47 #include <type_traits>
48 
49 //======================================================================================//
50 //
51 #if !defined(TIMEMORY_FOLD_EXPRESSION)
52 # if defined(CXX17)
53 # define TIMEMORY_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
54 # else
55 # define TIMEMORY_FOLD_EXPRESSION(...) \
56  ::tim::consume_parameters(::std::initializer_list<int>{ (__VA_ARGS__, 0)... })
57 # endif
58 #endif
59 
60 //======================================================================================//
61 //
62 #if !defined(TIMEMORY_FOLD_EXPANSION)
63 # define TIMEMORY_FOLD_EXPANSION(TYPE, SIZE, ...) \
64  std::array<TYPE, SIZE>({ (::tim::consume_parameters(), __VA_ARGS__)... });
65 #endif
66 
67 //======================================================================================//
68 //
69 #if !defined(TIMEMORY_RETURN_FOLD_EXPRESSION)
70 # define TIMEMORY_RETURN_FOLD_EXPRESSION(...) \
71  ::std::make_tuple((::tim::consume_parameters(), __VA_ARGS__)...)
72 #endif
73 
74 //======================================================================================//
75 //
76 #if !defined(TIMEMORY_DECLARE_EXTERN_TEMPLATE)
77 # define TIMEMORY_DECLARE_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
78 #endif
79 
80 //======================================================================================//
81 //
82 #if !defined(TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE)
83 # define TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE(...) template __VA_ARGS__;
84 #endif
85 
86 //======================================================================================//
87 //
88 #if !defined(TIMEMORY_ESC)
89 # define TIMEMORY_ESC(...) __VA_ARGS__
90 #endif
91 
92 //======================================================================================//
93 //
94 #if !defined(TIMEMORY_DELETED_OBJECT)
95 # define TIMEMORY_DELETED_OBJECT(NAME) \
96  NAME() = delete; \
97  NAME(const NAME&) = delete; \
98  NAME(NAME&&) = delete; \
99  NAME& operator=(const NAME&) = delete; \
100  NAME& operator=(NAME&&) = delete;
101 #endif
102 
103 //======================================================================================//
104 //
105 #if !defined(TIMEMORY_DELETE_COPY_MOVE_OBJECT)
106 # define TIMEMORY_DELETE_COPY_MOVE_OBJECT(NAME) \
107  NAME(const NAME&) = delete; \
108  NAME(NAME&&) = delete; \
109  NAME& operator=(const NAME&) = delete; \
110  NAME& operator=(NAME&&) = delete;
111 #endif
112 
113 //======================================================================================//
114 //
115 #if !defined(TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT)
116 # define TIMEMORY_DEFAULT_MOVE_ONLY_OBJECT(NAME) \
117  NAME(const NAME&) = delete; \
118  NAME(NAME&&) noexcept = default; \
119  NAME& operator=(const NAME&) = delete; \
120  NAME& operator=(NAME&&) noexcept = default;
121 #endif
122 
123 //======================================================================================//
124 //
125 #if !defined(TIMEMORY_DEFAULT_OBJECT)
126 # define TIMEMORY_DEFAULT_OBJECT(NAME) \
127  NAME() = default; \
128  NAME(const NAME&) = default; \
129  NAME(NAME&&) noexcept = default; \
130  NAME& operator=(const NAME&) = default; \
131  NAME& operator=(NAME&&) noexcept = default;
132 #endif
133 
134 //======================================================================================//
135 //
136 #if !defined(TIMEMORY_EXCEPTION)
137 # define TIMEMORY_EXCEPTION(...) \
138  { \
139  std::stringstream _errmsg; \
140  _errmsg << __VA_ARGS__; \
141  perror(_errmsg.str().c_str()); \
142  std::cerr << _errmsg.str() << std::endl; \
143  std::exit(EXIT_FAILURE); \
144  }
145 #endif
146 
147 //======================================================================================//
148 //
149 #if !defined(TIMEMORY_TESTING_EXCEPTION) && defined(TIMEMORY_INTERNAL_TESTING)
150 # define TIMEMORY_TESTING_EXCEPTION(...) \
151  { \
152  TIMEMORY_EXCEPTION(__VA_ARGS__) \
153  }
154 #elif !defined(TIMEMORY_TESTING_EXCEPTION)
155 # define TIMEMORY_TESTING_EXCEPTION(...) \
156  {}
157 #endif
158 
159 //======================================================================================//
160 //
161 #if !defined(TIMEMORY_TUPLE_ACCESSOR)
162 # define TIMEMORY_TUPLE_ACCESSOR(INDEX, TUPLE, NAME) \
163  auto& NAME() { return std::get<INDEX>(TUPLE); } \
164  const auto& NAME() const { return std::get<INDEX>(TUPLE); }
165 #endif
166 
167 //======================================================================================//
168 //
169 namespace tim
170 {
171 //
172 /// Alias template make_integer_sequence
173 template <typename Tp, Tp Num>
174 using make_integer_sequence = std::make_integer_sequence<Tp, Num>;
175 //
176 /// Alias template index_sequence
177 template <size_t... Idx>
178 using index_sequence = std::integer_sequence<size_t, Idx...>;
179 //
180 /// Alias template make_index_sequence
181 template <size_t Num>
182 using make_index_sequence = std::make_integer_sequence<size_t, Num>;
183 //
184 /// Alias template index_sequence_for
185 template <typename... Types>
187 //
188 /// Alias template for enable_if
189 template <bool B, typename T = int>
190 using enable_if_t = typename std::enable_if<B, T>::type;
191 //
192 /// Alias template for decay
193 template <typename T>
194 using decay_t = typename std::decay<T>::type;
195 //
196 template <bool B, typename Lhs, typename Rhs>
197 using conditional_t = typename std::conditional<B, Lhs, Rhs>::type;
198 //
199 template <typename T>
200 using remove_cv_t = typename std::remove_cv<T>::type;
201 //
202 template <typename T>
203 using remove_const_t = typename std::remove_const<T>::type;
204 //
205 template <int N>
206 using priority_constant = std::integral_constant<int, N>;
207 //
208 //--------------------------------------------------------------------------------------//
209 //
210 template <typename T>
211 struct identity
212 {
213  using type = T;
214 };
215 //
216 template <typename T>
217 using identity_t = typename identity<T>::type;
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
231 template <typename... Tp>
232 struct type_list
233 {};
234 //
235 //--------------------------------------------------------------------------------------//
236 //
237 /// \struct tim::type_list_element
238 /// \brief Variant of `std::tuple_element` for \ref tim::type_list
239 template <size_t Idx, typename Tp>
240 struct type_list_element;
241 
242 namespace internal
243 {
244 template <size_t Idx, size_t TargIdx, typename... Tail>
245 struct type_list_element;
246 
247 template <size_t Idx, size_t TargIdx>
248 struct 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 
257 template <size_t Idx, size_t TargIdx, typename Tp, typename... Tail>
258 struct 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 
266 template <size_t Idx, typename... Types>
267 struct type_list_element<Idx, type_list<Types...>>
268 {
269  using type = typename internal::type_list_element<0, Idx, Types...>::type;
270 };
271 
272 template <size_t Idx, typename Tp>
273 using 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
279 template <typename... ArgsT>
280 TIMEMORY_ALWAYS_INLINE void
281 consume_parameters(ArgsT&&...) TIMEMORY_HIDDEN TIMEMORY_NEVER_INSTRUMENT;
282 //
283 template <typename... ArgsT>
284 void
286 {}
287 //
288 //--------------------------------------------------------------------------------------//
289 //
290 template <typename Tp, typename DeleterT, typename Tag>
291 class singleton;
292 //
293 //--------------------------------------------------------------------------------------//
294 //
295 namespace cupti
296 {
297 struct result;
298 }
299 //
300 //--------------------------------------------------------------------------------------//
301 //
302 namespace 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...); }
310 struct base
311 {};
312 //
313 //--------------------------------------------------------------------------------------//
314 //
315 } // namespace crtp
316 //
317 //--------------------------------------------------------------------------------------//
318 //
319 namespace 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 //
332 template <typename... Tp>
334 {};
335 //
336 //--------------------------------------------------------------------------------------//
337 //
338 } // namespace mpl
339 //
340 //--------------------------------------------------------------------------------------//
341 //
342 namespace scope
343 {
344 //
345 //--------------------------------------------------------------------------------------//
346 //
347 /// \struct tim::scope::tree
348 /// \brief Dummy struct to designates tree (hierarchical) storage. This scope (default)
349 /// maintains nesting in the call-graph storage. In this scoping mode, the results
350 /// will be separated from each other based on the identifier AND the current number
351 /// of component instances in a "start" region. E.g. for two components with the
352 /// same identifiers where the first calls start, then the second calls start then
353 /// the second will be at a depth of +1 relative to the first (i.e. a child of the first).
354 struct tree : std::integral_constant<int, 2>
355 {};
356 //
357 //--------------------------------------------------------------------------------------//
358 //
359 /// \struct tim::scope::flat
360 /// \brief Dummy struct to designates flat (no hierarchy) storage.
361 /// When flat scoping is globally enabled, all entries to the call-graph storage at
362 /// entered at a depth of zero. Thus, if you want a report of all the function calls
363 /// and their total values for each identifier, flat scoping should be globally enabled.
364 /// This can be combined with timeline scoping to produce results where every measurement
365 /// is its own call-graph entry at a depth of zero (produces a large amount of data).
366 /// Flat-scoping can be enabled at the component bundler level also, there are two
367 /// ways to do this: (1) to enable flat-scoping for all instances of the bundle, add \ref
368 /// tim::quirk::flat_scope to the template parameters of the bundler; (2) to enable
369 /// flat-scoping for specific bundler instances, pass \code{.cpp}
370 /// tim::quirk::config<tim::quirk::flat_scope, ...>{} \endcode as the second argument to
371 /// the constructor of the bundle.
372 struct flat : std::integral_constant<int, 0>
373 {};
374 //
375 //--------------------------------------------------------------------------------------//
376 //
377 /// \struct tim::scope::timeline
378 /// \brief Dummy struct to designates timeline (hierarchical, non-duplicated) storage.
379 /// It is meaningless by itself and should be combined with \ref tim::scope::tree or
380 /// \ref tim::scope::flat. A tree timeline has all the hierarchy properties of the
381 /// tree scope but entries at the same depth with the same identifiers are separated
382 /// entries in the resuls.
383 /// Timeline-scoping can be enabled at the component bundler level also, there are two
384 /// ways to do this: (1) to enable timeline-scoping for all instances of the bundle, add
385 /// \ref tim::quirk::timeline_scope to the template parameters of the bundler; (2) to
386 /// enable timeline-scoping for specific bundler instances, pass \code{.cpp}
387 /// tim::quirk::config<tim::quirk::timeline_scope, ...>{} \endcode as the second argument
388 /// to the constructor of the bundle.
389 struct timeline : std::integral_constant<int, 1>
390 {};
391 //
392 //--------------------------------------------------------------------------------------//
393 //
394 static constexpr size_t scope_count = 3;
395 using data_type = std::bitset<scope_count>;
396 using input_type = std::array<bool, scope_count>;
397 //
398 //--------------------------------------------------------------------------------------//
399 //
400 inline input_type&
402 {
403  static input_type _instance{ { false, false, false } };
404  return _instance;
405 }
406 //
407 //--------------------------------------------------------------------------------------//
408 //
409 template <typename Arg, size_t... Idx>
410 static TIMEMORY_HOT_INLINE auto
411 generate(Arg&& arg, index_sequence<Idx...>)
412 {
413  static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
414  data_type ret;
415  TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, arg[Idx]));
416  return ret;
417 }
418 //
419 //--------------------------------------------------------------------------------------//
420 //
421 template <size_t... Idx>
422 static TIMEMORY_HOT_INLINE auto
423 either(data_type ret, data_type arg, index_sequence<Idx...>)
424 {
425  static_assert(sizeof...(Idx) <= scope_count, "Error! Bad index sequence size");
426  TIMEMORY_FOLD_EXPRESSION(ret.set(Idx, ret.test(Idx) || arg.test(Idx)));
427  return ret;
428 }
429 //
430 //--------------------------------------------------------------------------------------//
431 //
432 static TIMEMORY_HOT_INLINE auto
433 get_default_bitset() -> data_type
434 {
435  return generate(get_fields(), make_index_sequence<scope_count>{});
436 }
437 //
438 //--------------------------------------------------------------------------------------//
439 /// \struct tim::scope::config
440 /// \brief this data type encodes the options of storage scope. The default is
441 /// hierarchical (tree) scope. Specification of flat scope overrides the hierarchy
442 /// scope, e.g. you cannot have a hierarchical flat scope. The timeline scope
443 /// is meaningless should a specification of tree or flat, thus the valid combinations
444 /// are: tree, flat, tree + timeline, flat + timeline.
445 struct config : public data_type
446 {
448  : data_type(get_default_bitset())
449  {}
450 
451  explicit config(const data_type& obj)
452  : data_type(obj)
453  {}
454 
455  explicit config(data_type&& obj) noexcept
456  : data_type(std::forward<data_type>(obj))
457  {}
458 
459  explicit config(bool _flat)
460  : data_type(generate(input_type{ { _flat, false, false } },
462  {}
463 
464  explicit config(bool _flat, bool _timeline)
465  : data_type(generate(input_type{ { _flat, _timeline, false } },
467  {}
468 
469  explicit config(bool _flat, bool _timeline, bool _tree)
470  : data_type(generate(input_type{ { _flat, _timeline, _tree } },
472  {}
473 
475  : config(false, false, false)
476  {}
477 
479  : config(true, false, false)
480  {}
481 
483  : config(false, true, false)
484  {}
485 
486  template <typename Arg, typename... Args,
487  std::enable_if_t<(std::is_same<Arg, tree>::value ||
488  std::is_same<Arg, flat>::value ||
489  std::is_same<Arg, timeline>::value),
490  int> = 0>
491  explicit config(Arg&& arg, Args&&... args)
492  {
493  *this += std::forward<Arg>(arg);
494  TIMEMORY_FOLD_EXPRESSION(*this += std::forward<Args>(args));
495  }
496 
497  ~config() = default;
498  config(const config&) = default;
499  config(config&&) noexcept = default;
500  config& operator=(const config&) = default;
501  config& operator=(config&&) noexcept = default;
502 
503  config& operator=(const data_type& rhs)
504  {
505  if(this != &rhs)
506  data_type::operator=(rhs);
507  return *this;
508  }
509 
510  config& operator=(data_type&& rhs) noexcept
511  {
512  if(this != &rhs)
513  data_type::operator=(std::forward<data_type>(rhs));
514  return *this;
515  }
516 
517  template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
518  std::is_same<T, flat>::value ||
519  std::is_same<T, timeline>::value),
520  int> = 0>
522  {
523  this->data_type::set(T::value, true);
524  return *this;
525  }
526 
527  using data_type::set;
528 
529  template <typename T, std::enable_if_t<(std::is_same<T, tree>::value ||
530  std::is_same<T, flat>::value ||
531  std::is_same<T, timeline>::value),
532  int> = 0>
533  config& set(bool val = true)
534  {
535  this->data_type::set(T::value, val);
536  return *this;
537  }
538 
539  TIMEMORY_NODISCARD bool is_flat() const { return this->test(flat::value); }
540  TIMEMORY_NODISCARD bool is_timeline() const { return this->test(timeline::value); }
541  // "tree" is default behavior so it returns true if nothing is set but gives
542  // priority to the flat setting
543  TIMEMORY_NODISCARD bool is_tree() const
544  {
545  return this->none() || (this->test(tree::value) && !this->test(flat::value));
546  }
547  TIMEMORY_NODISCARD bool is_flat_timeline() const
548  {
549  return (is_flat() && is_timeline());
550  }
551  TIMEMORY_NODISCARD bool is_tree_timeline() const
552  {
553  return (is_tree() && is_timeline());
554  }
555 
556  template <bool ForceFlatT>
557  TIMEMORY_NODISCARD bool is_flat() const
558  {
559  return (ForceFlatT) ? true : this->test(flat::value);
560  }
561 
562  template <bool ForceTreeT, bool ForceTimeT>
563  TIMEMORY_NODISCARD bool is_tree() const
564  {
565  return (ForceTreeT)
566  ? true
567  : ((ForceTimeT) ? false
568  : (this->none() || (this->test(tree::value) &&
569  !this->test(flat::value))));
570  }
571 
572  friend std::ostream& operator<<(std::ostream& os, const config& obj)
573  {
574  std::stringstream ss;
575  ss << std::boolalpha << "tree: " << obj.is_tree() << ", flat: " << obj.is_flat()
576  << ", timeline: " << obj.is_timeline()
577  << ". Values: flat::value = " << obj.test(flat::value)
578  << ", timeline::value = " << obj.test(timeline::value)
579  << ", tree::value = " << obj.test(tree::value);
580  os << ss.str();
581  return os;
582  }
583 
584  template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
585  typename ForceTimeT = false_type>
586  uint64_t compute_depth(uint64_t _current)
587  {
588  static_assert(!(ForceTreeT::value && ForceFlatT::value),
589  "Error! Type cannot enforce tree-based call-stack depth storage "
590  "and flat call-stack depth storage simulatenously");
591  // flat: always at depth of 1
592  // tree: features nesting
593  // timeline: features nesting if not flat and depth of 1 if flat
594  if(ForceFlatT::value || is_flat())
595  {
596  // flat + timeline will be differentiated via compute_hash
597  // flat + tree is invalid and flat takes precedence
598  // printf("compute_depth is flat at %i\n", (int) _current);
599  return 1;
600  }
601  // if not flat, return the nested depth and compute_hash will account
602  // for whether the entry is a duplicate or not
603  // printf("compute_depth is tree or timeline at %i\n", (int) _current);
604  return _current + 1;
605  }
606 
607  template <typename ForceTreeT = false_type, typename ForceFlatT = false_type,
608  typename ForceTimeT = false_type>
609  uint64_t compute_hash(uint64_t _id, uint64_t _depth, uint64_t& _counter)
610  {
611  // flat/tree: always compute the same hash for a given depth and key
612  // timeline: uses a counter to differentiate idential hashes occurring at diff
613  // time points.
614  // below is a fall-through (i.e. not an if-else) bc either tree or flat can be
615  // combined with timeline but in the case of tree + flat, flat will take
616  // precedence.
617  if(is_tree<ForceTreeT::value, ForceTimeT::value>() ||
618  is_flat<ForceFlatT::value>())
619  {
620  // printf("compute_hash is tree or flat at %i\n", (int) _depth);
621  _id = get_combined_hash_id(_id, _depth);
622  // _id ^= _depth;
623  }
624  if(ForceTimeT::value || is_timeline())
625  {
626  // printf("compute_hash is timeline at %i\n", (int) _depth);
627  _id = get_combined_hash_id(_id, _counter++);
628  // _id ^= _counter++;
629  }
630  // printf("compute_hash is %i at depth %i (counter = %i)\n", (int) _id, (int)
631  // _depth,
632  // (int) _counter);
633  return _id;
634  }
635 };
636 //
637 //--------------------------------------------------------------------------------------//
638 // clang-format off
639 static TIMEMORY_INLINE config
640 get_default() TIMEMORY_HOT;
641 TIMEMORY_INLINE config
642 operator+(config _lhs, tree) TIMEMORY_HOT;
643 TIMEMORY_INLINE config
644 operator+(config _lhs, flat) TIMEMORY_HOT;
645 TIMEMORY_INLINE config
646 operator+(config _lhs, timeline) TIMEMORY_HOT;
647 TIMEMORY_INLINE config
648 operator+(config _lhs, config _rhs) TIMEMORY_HOT;
649 // clang-format on
650 //--------------------------------------------------------------------------------------//
651 //
652 static TIMEMORY_HOT_INLINE auto
653 get_default() -> config
654 {
655  return config{ get_default_bitset() };
656 }
657 //
658 //--------------------------------------------------------------------------------------//
659 //
660 TIMEMORY_HOT_INLINE auto
662 {
663  _lhs.set(tree::value, true);
664  return _lhs;
665 }
666 //
667 //--------------------------------------------------------------------------------------//
668 //
669 TIMEMORY_HOT_INLINE auto
671 {
672  _lhs.set(flat::value, true);
673  return _lhs;
674 }
675 //
676 //--------------------------------------------------------------------------------------//
677 //
678 TIMEMORY_HOT_INLINE auto
680 {
681  _lhs.set(timeline::value, true);
682  return _lhs;
683 }
684 //
685 //--------------------------------------------------------------------------------------//
686 //
687 TIMEMORY_HOT_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 
717  destructor& operator=(destructor&& rhs) noexcept
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 
729 private:
730  std::function<void()> m_functor = []() {};
731 };
732 //
733 //--------------------------------------------------------------------------------------//
734 //
735 } // namespace scope
736 //
737 //--------------------------------------------------------------------------------------//
738 //
739 namespace 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 ///
751 struct 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 //
770 namespace 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 
800 namespace std
801 {
802 template <size_t Idx, typename... Types>
803 struct 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 
811 namespace tim
812 {
813 namespace cereal
814 {
815 namespace detail
816 {
817 template <typename Tp>
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
#define TIMEMORY_HIDDEN
Definition: macros.h:186
a generic type for prioritizing a function call to the base class over derived functions,...
Definition: types.hpp:311
void audit(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:921
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
config operator+(config _lhs, config _rhs)
Definition: types.hpp:688
std::array< bool, scope_count > input_type
Definition: types.hpp:396
std::bitset< scope_count > data_type
Definition: types.hpp:395
input_type & get_fields()
Definition: types.hpp:401
Definition: kokkosp.cpp:38
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
void consume_parameters(ArgsT &&...) TIMEMORY_HIDDEN
Definition: types.hpp:285
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
hash_value_t get_combined_hash_id(hash_value_t _lhs, Tp &&_rhs)
Definition: types.hpp:167
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
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:446
config(Arg &&arg, Args &&... args)
Definition: types.hpp:491
config(data_type &&obj) noexcept
Definition: types.hpp:455
config(const config &)=default
bool is_flat() const
Definition: types.hpp:557
config(config &&) noexcept=default
bool is_tree() const
Definition: types.hpp:563
config & operator+=(T)
Definition: types.hpp:521
uint64_t compute_depth(uint64_t _current)
Definition: types.hpp:586
config & set(bool val=true)
Definition: types.hpp:533
config(timeline)
Definition: types.hpp:482
config & operator=(data_type &&rhs) noexcept
Definition: types.hpp:510
bool is_tree_timeline() const
Definition: types.hpp:551
bool is_flat_timeline() const
Definition: types.hpp:547
config(bool _flat, bool _timeline, bool _tree)
Definition: types.hpp:469
config(bool _flat)
Definition: types.hpp:459
bool is_flat() const
Definition: types.hpp:539
bool is_timeline() const
Definition: types.hpp:540
uint64_t compute_hash(uint64_t _id, uint64_t _depth, uint64_t &_counter)
Definition: types.hpp:609
bool is_tree() const
Definition: types.hpp:543
config(bool _flat, bool _timeline)
Definition: types.hpp:464
friend std::ostream & operator<<(std::ostream &os, const config &obj)
Definition: types.hpp:572
config(const data_type &obj)
Definition: types.hpp:451
provides an object which can be returned from functions that will execute the lambda provided during ...
Definition: types.hpp:700
destructor(destructor &&rhs) noexcept
Definition: types.hpp:711
destructor & operator=(destructor &&rhs) noexcept
Definition: types.hpp:717
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:373
Dummy struct to designates timeline (hierarchical, non-duplicated) storage. It is meaningless by itse...
Definition: types.hpp:390
Dummy struct to designates tree (hierarchical) storage. This scope (default) maintains nesting in the...
Definition: types.hpp:355
#define TIMEMORY_FOLD_EXPRESSION(...)
Definition: types.hpp:55
typename typename typename
Definition: types.hpp:226
type_list
Definition: types.hpp:211