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.
node.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 * \file timemory/operations/types/push_node.hpp
27 * \brief Definition for various functions for push_node in operations
28 */
29
30#pragma once
31
39
40namespace tim
41{
42namespace operation
43{
44//
45template <typename Up>
46static constexpr bool
47storage_is_nullptr_t()
48{
49 return std::is_same<
50 decay_t<decltype(operation::get_storage<Up>{}(std::declval<Up&>()))>,
51 std::nullptr_t>::value;
52}
53//
54//--------------------------------------------------------------------------------------//
55//
56//
57//
58//--------------------------------------------------------------------------------------//
59//
60template <typename Tp>
62{
63 using type = Tp;
64
65 TIMEMORY_DEFAULT_OBJECT(push_node)
66
67 TIMEMORY_HOT push_node(type& obj, scope::config _scope, hash_value_t _hash)
68 {
69 (*this)(obj, _scope, _hash);
70 }
71
72 TIMEMORY_HOT push_node(type& obj, scope::config _scope, string_view_cref_t _key)
73 : push_node(obj, _scope, get_hash_id(_key))
74 {}
75
76 TIMEMORY_HOT auto operator()(type& obj, scope::config _scope,
77 hash_value_t _hash) const
78 {
80 return sfinae(obj, 0, 0, 0, _scope, _hash);
81 }
82
83 TIMEMORY_HOT auto operator()(type& obj, scope::config _scope,
84 string_view_cref_t _key) const
85 {
86 return (*this)(obj, _scope, get_hash_id(_key));
87 }
88
89private:
90 // typical resolution: variadic bundle of components, component
91 template <typename Up, typename... Args>
92 auto sfinae(Up& obj, int, int, int, Args&&... args) const
93 -> decltype(obj.push(std::forward<Args>(args)...))
94 {
95 return obj.push(std::forward<Args>(args)...);
96 }
97
98 // typical resolution: variadic bundle of components, component
99 template <typename Up, typename... Args>
100 auto sfinae(Up& obj, int, int, long, Args&&...) const -> decltype(obj.push())
101 {
102 return obj.push();
103 }
104
105 // typical resolution: component inheriting from component::base<T, V>
106 template <typename Up, typename Vp = typename Up::value_type,
107 typename StorageT = storage<Up, Vp>,
108 enable_if_t<trait::uses_value_storage<Up, Vp>::value, int> = 0>
109 TIMEMORY_HOT auto sfinae(Up& _obj, int, long, long, scope::config _scope,
110 hash_value_t _hash,
111 enable_if_t<!storage_is_nullptr_t<Up>(), int> = 0) const
112 -> decltype(_obj.get_iterator())
113 {
114 using storage_type = StorageT;
115 constexpr bool force_flat_v = trait::flat_storage<Tp>::value;
116 constexpr bool force_time_v = trait::timeline_storage<Tp>::value;
117 if(!operation::get_is_on_stack<type, false>{}(_obj))
118 {
119 // reset some state
120 operation::set_is_on_stack<type>{}(_obj, true);
121 operation::set_is_flat<type>{}(_obj, _scope.is_flat() || force_flat_v);
122
123 auto _storage = operation::get_storage<type>{}(_obj);
124 // if storage is a nullptr, iterator is stale
125 if(!_storage)
126 return nullptr;
127
128 // get the current depth
129 auto _beg_depth = operation::get_depth<storage_type>{}(*_storage);
130 // check against max depth when not flat
131 if(!operation::get_is_flat<type, false>{}(_obj))
132 {
134 if(_settings && _beg_depth + 1 > _settings->get_max_depth())
135 {
136 operation::set_is_on_stack<type>{}(_obj, false);
137 return nullptr;
138 }
139 }
140 // assign iterator to the insertion point in storage
141 operation::set_iterator<type>{}(
142 _obj, operation::insert<storage_type>{}(*_storage, _scope, _obj, _hash));
143 // get the new depth
144 auto _end_depth = operation::get_depth<storage_type>{}(*_storage);
145 // configure the depth change state
146 operation::set_depth_change<type>{}(
147 _obj,
148 (_beg_depth < _end_depth) || (_scope.is_timeline() || force_time_v));
149 // add to stack
150 operation::stack_push<storage_type>{}(*_storage, &_obj);
151 }
152 return _obj.get_iterator();
153 }
154
155 // no member function or does not satisfy mpl condition
156 template <typename Up, typename... Args>
157 void sfinae(Up&, long, long, long, Args&&...) const
158 {}
159};
160//
161//--------------------------------------------------------------------------------------//
162//
163//
164//--------------------------------------------------------------------------------------//
165//
166template <typename Tp>
168{
169 using type = Tp;
170
171 TIMEMORY_DEFAULT_OBJECT(pop_node)
172
173 TIMEMORY_HOT explicit pop_node(type& obj) { (*this)(obj); }
174
175 template <typename Arg, typename... Args>
176 TIMEMORY_HOT explicit pop_node(type& obj, Arg&& arg, Args&&... args)
177 {
178 (*this)(obj, std::forward<Arg>(arg), std::forward<Args>(args)...);
179 }
180
181 TIMEMORY_HOT auto operator()(type& obj) const { return sfinae(obj, 0, 0, 0); }
182
183 template <typename Arg, typename... Args>
184 TIMEMORY_HOT auto operator()(type& obj, Arg&& arg, Args&&... args) const
185 {
186 return sfinae(obj, 0, 0, 0, std::forward<Arg>(arg), std::forward<Args>(args)...);
187 }
188
189private:
190 // typical resolution: variadic bundle of components, component
191 template <typename Up, typename... Args>
192 auto sfinae(Up& obj, int, int, int, Args&&... args) const
193 -> decltype(obj.pop(std::forward<Args>(args)...))
194 {
195 return obj.pop(std::forward<Args>(args)...);
196 }
197
198 // typical resolution: variadic bundle of components, component
199 template <typename Up, typename... Args>
200 auto sfinae(Up& obj, int, int, long, Args&&...) const -> decltype(obj.pop())
201 {
202 return obj.pop();
203 }
204
205 // typical resolution: component inheriting from component::base<T, V>
206 template <typename Up, typename Vp = typename Up::value_type,
207 typename StorageT = storage<Up, Vp>,
208 enable_if_t<trait::uses_value_storage<Up, Vp>::value, int> = 0>
209 TIMEMORY_HOT auto sfinae(Up& _obj, int, long, long,
210 enable_if_t<!storage_is_nullptr_t<Up>(), int> = 0) const
211 -> decltype(_obj.get_iterator())
212 {
213 using storage_type = StorageT;
214
215 // return
216 if(operation::get_is_invalid<Up, false>{}(_obj))
217 return nullptr;
218
219 if(operation::get_is_on_stack<type, true>{}(_obj) && _obj.get_iterator())
220 {
221 auto _storage = operation::get_storage<type>{}(_obj);
222 assert(_storage != nullptr);
223
224 // if storage is null, iterator is stale which means targ and stats are too
225 if(!_storage)
226 return nullptr;
227
228 operation::set_is_on_stack<type>{}(_obj, false);
229 auto&& itr = _obj.get_iterator();
230 type& targ = itr->obj();
231 auto& stats = itr->stats();
232
233 // reset depth change and set valid state on target
234 operation::set_depth_change<type>{}(_obj, false);
235 operation::set_is_invalid<type>{}(targ, false);
236 // add measurement to target in storage
237 operation::plus<type>(targ, _obj);
238 // add the secondary data
239 operation::add_secondary<type>(_storage, itr, _obj);
240 // update the statistics
241 operation::add_statistics<type>(_obj, stats);
242 // if not finalizing manipulate call-stack hierarchy
243 if(!storage_type::is_finalizing())
244 {
245 if(operation::get_is_flat<type, false>{}(_obj))
246 {
247 // just pop if flat
248 operation::stack_pop<storage_type>{}(*_storage, &_obj);
249 }
250 else
251 {
252 // get depth and then pop
253 auto _beg_depth = operation::get_depth<storage_type>{}(_storage);
254 operation::pop<storage_type>{}(*_storage);
255 operation::stack_pop<storage_type>{}(*_storage, &_obj);
256 // get depth and determine if depth change occurred
257 auto _end_depth = operation::get_depth<storage_type>{}(_storage);
258 operation::set_depth_change<type>{}(_obj, _beg_depth > _end_depth);
259 }
260 }
261 operation::set_is_running<type>{}(targ, false);
262 }
263 return _obj.get_iterator();
264 }
265
266 // no member function or does not satisfy mpl condition
267 template <typename Up, typename... Args>
268 void sfinae(Up&, long, long, long, Args&&...) const
269 {}
270};
271//
272//--------------------------------------------------------------------------------------//
273//
274} // namespace operation
275} // namespace tim
Definition for various functions for add_secondary in operations.
Definition for various functions for add_statistics in operations.
hash_value_t get_hash_id(Tp &&_prefix)
Definition: types.hpp:143
size_t hash_value_t
Definition: types.hpp:84
void pop(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:739
void push(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:704
Definition: kokkosp.cpp:39
const std::string & string_view_cref_t
Definition: language.hpp:103
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
char argparse::argument_parser tim::settings * _settings
Definition: config.cpp:255
The declaration for the types for operations without definitions.
Include the macros for operations.
Definition for various functions for math in operations.
Declare the operations types.
auto operator()(type &obj, Arg &&arg, Args &&... args) const
Definition: node.hpp:184
auto operator()(type &obj) const
Definition: node.hpp:181
pop_node(type &obj, Arg &&arg, Args &&... args)
Definition: node.hpp:176
auto operator()(type &obj, scope::config _scope, string_view_cref_t _key) const
Definition: node.hpp:83
push_node(type &obj, scope::config _scope, string_view_cref_t _key)
Definition: node.hpp:72
auto operator()(type &obj, scope::config _scope, hash_value_t _hash) const
Definition: node.hpp:76
this data type encodes the options of storage scope. The default is hierarchical (tree) scope....
Definition: types.hpp:453
static settings * instance()
Definition: settings.hpp:536