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.
add_secondary.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/add_secondary.hpp
27 * \brief Definition for various functions for add_secondary in operations
28 */
29
30#pragma once
31
36
37namespace tim
38{
39namespace operation
40{
41namespace internal
42{
43//
44//--------------------------------------------------------------------------------------//
45//
46template <typename Tp, bool>
47struct add_secondary;
48//
49template <typename Tp>
50struct add_secondary<Tp, true>
51{
52 using type = Tp;
53 using string_t = std::string;
54
55 TIMEMORY_DEFAULT_OBJECT(add_secondary)
56
57 //----------------------------------------------------------------------------------//
58 // if secondary data explicitly specified
59 //
60 template <typename Storage, typename Iterator>
61 add_secondary(Storage* _storage, Iterator _itr, const type& _rhs)
62 {
63 if(!_storage || !settings::add_secondary())
64 return;
65 (*this)(_storage, _itr, _rhs);
66 }
67
68 //----------------------------------------------------------------------------------//
69 // add_secondary called on type
70 //
71 template <typename... Args>
72 add_secondary(type& _rhs, Args&&... args)
73 {
75 return;
76 (*this)(_rhs, std::forward<Args>(args)...);
77 }
78
79 //----------------------------------------------------------------------------------//
80 // if secondary data explicitly specified
81 //
82 template <typename Storage, typename Iterator, typename Up>
83 auto operator()(Storage* _storage, Iterator _itr, const Up& _rhs) const
84 {
85 if(!_storage)
86 return;
87 using map_type = decay_t<decltype(_rhs.get_secondary())>;
88 using value_type = typename map_type::mapped_type;
89 using secondary_data_t = std::tuple<Iterator, const string_t&, value_type>;
90 for(const auto& _data : _rhs.get_secondary())
91 {
92 storage_sfinae(_storage, 0,
93 secondary_data_t{ _itr, _data.first, _data.second });
94 }
95 }
96
97 //----------------------------------------------------------------------------------//
98 // add_secondary called on type
99 //
100 template <typename... Args>
101 auto operator()(type& _rhs, Args&&... args) const
102 {
103 return sfinae(_rhs, 0, std::forward<Args>(args)...);
104 }
105
106 //----------------------------------------------------------------------------------//
107 // if no storage type
108 //
109 template <typename... Args>
110 add_secondary(std::nullptr_t, Args...)
111 {}
112
113 template <typename... Args>
114 auto operator()(std::nullptr_t, Args...)
115 {}
116
117private:
118 //----------------------------------------------------------------------------------//
119 // If the component has a add_secondary(Args...) member function
120 //
121 template <typename Up, typename... Args>
122 auto sfinae(Up& _obj, int, Args&&... args) const
123 -> decltype(_obj.add_secondary(std::forward<Args>(args)...))
124 {
125 return _obj.add_secondary(std::forward<Args>(args)...);
126 }
127
128 //----------------------------------------------------------------------------------//
129 // If the component does not have a add_secondary(Args...) member function
130 //
131 template <typename Up, typename... Args>
132 void sfinae(Up&, long, Args&&...) const
133 {}
134
135 //----------------------------------------------------------------------------------//
136 // If the storage can append secondary data
137 //
138 template <typename Storage, typename DataT>
139 auto storage_sfinae(Storage* _storage, int, DataT&& _data) const
140 -> decltype(_storage->append(std::forward<DataT>(_data)))
141 {
142 return _storage->append(std::forward<DataT>(_data));
143 }
144
145 //----------------------------------------------------------------------------------//
146 // If the storage can NOT append secondary data
147 //
148 template <typename Storage, typename DataT>
149 void storage_sfinae(Storage*, long, DataT&&) const
150 {}
151};
152//
153//
154//--------------------------------------------------------------------------------------//
155//
156template <typename Tp>
157struct add_secondary<Tp, false>
158{
159 using type = Tp;
160 using string_t = std::string;
161
162 TIMEMORY_DEFAULT_OBJECT(add_secondary)
163
164 //----------------------------------------------------------------------------------//
165 // check if secondary data implicitly specified
166 //
167 template <typename Storage, typename Iterator>
168 add_secondary(Storage* _storage, Iterator _itr, const type& _rhs)
169 {
170 (*this)(_storage, _itr, _rhs);
171 }
172
173 //----------------------------------------------------------------------------------//
174 // add_secondary called on type
175 //
176 template <typename... Args>
177 add_secondary(type& _rhs, Args&&... args)
178 {
179 (*this)(_rhs, std::forward<Args>(args)...);
180 }
181
182 //----------------------------------------------------------------------------------//
183 // if secondary data explicitly specified
184 //
185 template <typename Storage, typename Iterator>
186 auto operator()(Storage* _storage, Iterator _itr, const type& _rhs) const
187 {
188 return storage_sfinae(_storage, _itr, _rhs, 0);
189 }
190
191 //----------------------------------------------------------------------------------//
192 // add_secondary called on type
193 //
194 template <typename... Args>
195 auto operator()(type& _rhs, Args&&... args) const
196 {
197 return sfinae(_rhs, 0, std::forward<Args>(args)...);
198 }
199
200 //----------------------------------------------------------------------------------//
201 // if no storage type
202 //
203 template <typename... Args>
204 add_secondary(std::nullptr_t, Args...)
205 {}
206
207 template <typename... Args>
208 auto operator()(std::nullptr_t, Args...)
209 {}
210
211private:
212 //----------------------------------------------------------------------------------//
213 // If the component has a get_secondary() member function
214 //
215 template <typename Storage, typename Iterator, typename Up>
216 auto storage_sfinae(Storage* _storage, Iterator _itr, const Up& _rhs, int) const
217 -> decltype(_rhs.get_secondary(), void())
218 {
219 if(_storage == nullptr || !settings::add_secondary())
220 return;
221
222 using map_type = decay_t<decltype(_rhs.get_secondary())>;
223 using value_type = typename map_type::mapped_type;
224 using secondary_data_t = std::tuple<Iterator, const string_t&, value_type>;
225 for(const auto& _data : _rhs.get_secondary())
226 _storage->append(secondary_data_t{ _itr, _data.first, _data.second });
227 }
228
229 //----------------------------------------------------------------------------------//
230 // If the component does not have a get_secondary() member function
231 //
232 template <typename Storage, typename Iterator>
233 void storage_sfinae(Storage*, Iterator, const type&, long) const
234 {}
235
236 //----------------------------------------------------------------------------------//
237 // If the component has a add_secondary(Args...) member function
238 //
239 template <typename Up, typename... Args>
240 auto sfinae(Up& _obj, int, Args&&... args) const
241 -> decltype(_obj.add_secondary(std::forward<Args>(args)...), void())
242 {
244 return;
245
246 _obj.add_secondary(std::forward<Args>(args)...);
247 }
248
249 //----------------------------------------------------------------------------------//
250 // If the component does not have a add_secondary(Args...) member function
251 //
252 template <typename Up, typename... Args>
253 void sfinae(Up&, long, Args&&...) const
254 {}
255};
256//
257} // namespace internal
258//
259//--------------------------------------------------------------------------------------//
260//
261///
262/// \struct tim::operation::add_secondary
263/// \tparam Tp Component type
264///
265/// \brief
266/// component contains secondary data resembling the original data
267/// but should be another node entry in the graph. These types
268/// must provide a get_secondary() member function and that member function
269/// must return a pair-wise iterable container, e.g. std::map, of types:
270/// - std::string
271/// - value_type or Tp
272///
273//
274//--------------------------------------------------------------------------------------//
275//
276template <typename Tp>
278: public internal::add_secondary<Tp, trait::secondary_data<Tp>::value>
279{
280 using type = Tp;
282 using base_type = internal::add_secondary<Tp, trait::secondary_data<Tp>::value>;
283
284 TIMEMORY_DEFAULT_OBJECT(add_secondary)
285
286 add_secondary(const type& _rhs, typename type::storage_type* _storage)
287 : base_type{ _storage, operation::get_iterator<Tp>{}(_rhs), _rhs }
288 {}
289
290 //----------------------------------------------------------------------------------//
291 // if secondary data explicitly specified
292 //
293 template <typename Storage, typename Iterator>
294 add_secondary(Storage* _storage, Iterator _itr, const type& _rhs)
295 : base_type{ _storage, _itr, _rhs }
296 {}
297
298 //----------------------------------------------------------------------------------//
299 // add_secondary called on type
300 //
301 template <typename... Args>
302 add_secondary(type& _rhs, Args&&... args)
303 : base_type{ _rhs, std::forward<Args>(args)... }
304 {}
305
306 //----------------------------------------------------------------------------------//
307 // add_secondary called without storage
308 //
309 template <typename... Args>
310 add_secondary(std::nullptr_t, Args...)
311 {}
312};
313//
314//--------------------------------------------------------------------------------------//
315//
316} // namespace operation
317} // namespace tim
std::string string_t
Definition: library.cpp:57
STL namespace.
return false
Definition: definition.hpp:326
Definition: kokkosp.cpp:39
add_secondary
Definition: settings.cpp:1677
typename std::decay< T >::type decay_t
Alias template for decay.
Definition: types.hpp:194
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
The declaration for the types for operations without definitions.
Include the macros for operations.
Declare the operations types.
component contains secondary data resembling the original data but should be another node entry in th...
internal::add_secondary< Tp, trait::secondary_data< Tp >::value > base_type
add_secondary(type &_rhs, Args &&... args)
add_secondary(std::nullptr_t, Args...)
add_secondary(Storage *_storage, Iterator _itr, const type &_rhs)
This operation attempts to call a member function which provides a pointer to a component which exist...
Definition: types.hpp:812
typename typename typename
Definition: types.hpp:226