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.
macros.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
29#include "timemory/dll.hpp"
30#include "timemory/macros.hpp"
31
32#include <string>
33#include <unordered_set>
34
35//--------------------------------------------------------------------------------------//
36//
37#if defined(TIMEMORY_USE_EXTERN) && !defined(TIMEMORY_USE_COMPONENT_EXTERN)
38# define TIMEMORY_USE_COMPONENT_EXTERN
39#endif
40
41#if !defined(TIMEMORY_USE_COMPONENT_EXTERN) && !defined(TIMEMORY_COMPONENT_SOURCE) && \
42 !defined(TIMEMORY_COMPONENT_HEADER_MODE)
43# define TIMEMORY_COMPONENT_HEADER_MODE
44#endif
45
46//--------------------------------------------------------------------------------------//
47//
48/**
49 * \macro TIMEMORY_DECLARE_COMPONENT
50 * \brief Declare a non-templated component type in the tim::component namespace
51 */
52
53#if !defined(TIMEMORY_DECLARE_COMPONENT)
54# define TIMEMORY_DECLARE_COMPONENT(NAME) \
55 namespace tim \
56 { \
57 namespace component \
58 { \
59 struct NAME; \
60 } \
61 namespace trait \
62 { \
63 template <> \
64 struct is_component<component::NAME> : true_type \
65 {}; \
66 } \
67 }
68#endif
69//
70//--------------------------------------------------------------------------------------//
71//
72/**
73 * \macro TIMEMORY_DECLARE_API_COMPONENTS
74 * \brief Declare a non-templated component type in the tim::component namespace
75 */
76
77#if !defined(TIMEMORY_DECLARE_API_COMPONENTS)
78# define TIMEMORY_DECLARE_API_COMPONENTS(API, ...) \
79 namespace tim \
80 { \
81 namespace trait \
82 { \
83 template <> \
84 struct api_components<API, void> \
85 { \
86 using type = type_list<__VA_ARGS__>; \
87 }; \
88 } \
89 }
90#endif
91//
92//--------------------------------------------------------------------------------------//
93//
94/**
95 * \macro TIMEMORY_SET_COMPONENT_APIS
96 * \brief Declare a component is part of one or more APIs
97 */
98
99#if !defined(TIMEMORY_SET_COMPONENT_API)
100# define TIMEMORY_SET_COMPONENT_API(COMP, ...) \
101 namespace tim \
102 { \
103 namespace trait \
104 { \
105 template <> \
106 struct component_apis<COMP> \
107 { \
108 using type = type_list<__VA_ARGS__>; \
109 }; \
110 } \
111 }
112#endif
113//
114//--------------------------------------------------------------------------------------//
115//
116/**
117 * \macro TIMEMORY_SET_TEMPLATE_COMPONENT_API
118 * \brief Declare a component is part of one or more APIs
119 */
120
121#if !defined(TIMEMORY_SET_TEMPLATE_COMPONENT_API)
122# define TIMEMORY_SET_TEMPLATE_COMPONENT_API(TARGS, TSPECIAL, ...) \
123 namespace tim \
124 { \
125 namespace trait \
126 { \
127 template <TARGS> \
128 struct component_apis<TSPECIAL> \
129 { \
130 using type = type_list<__VA_ARGS__>; \
131 }; \
132 } \
133 }
134#endif
135//
136//--------------------------------------------------------------------------------------//
137//
138/**
139 * \macro TIMEMORY_BUNDLE_INDEX
140 * \brief Declare a bundle index
141 */
142
143#if !defined(TIMEMORY_BUNDLE_INDEX)
144# define TIMEMORY_BUNDLE_INDEX(NAME, IDX) \
145 namespace tim \
146 { \
147 namespace component \
148 { \
149 static constexpr size_t NAME = IDX; \
150 } \
151 }
152#endif
153//
154//--------------------------------------------------------------------------------------//
155//
156/**
157 * \macro TIMEMORY_DECLARE_TEMPLATE_COMPONENT
158 * \brief Declare a templated component type in the tim::component namespace
159 */
160
161#if !defined(TIMEMORY_DECLARE_TEMPLATE_COMPONENT)
162# define TIMEMORY_DECLARE_TEMPLATE_COMPONENT(NAME, ...) \
163 namespace tim \
164 { \
165 namespace component \
166 { \
167 template <__VA_ARGS__> \
168 struct NAME; \
169 } \
170 }
171#endif
172//
173//--------------------------------------------------------------------------------------//
174//
175/**
176 * \macro TIMEMORY_TEMPLATE_COMPONENT
177 * \brief Declare a templated component type in the tim::component namespace
178 */
179#if !defined(TIMEMORY_TEMPLATE_COMPONENT)
180# define TIMEMORY_TEMPLATE_COMPONENT(NAME, TEMPLATE_PARAM, ...) \
181 namespace tim \
182 { \
183 namespace component \
184 { \
185 template <TEMPLATE_PARAM> \
186 struct NAME; \
187 } \
188 namespace trait \
189 { \
190 template <TEMPLATE_PARAM> \
191 struct is_component<component::NAME<__VA_ARGS__>> : true_type \
192 {}; \
193 } \
194 }
195#endif
196//
197//--------------------------------------------------------------------------------------//
198//
199/**
200 * \macro TIMEMORY_COMPONENT_ALIAS
201 * \brief Declare a non-templated alias to a component in the tim::component namespace
202 */
203
204#if !defined(TIMEMORY_COMPONENT_ALIAS)
205# define TIMEMORY_COMPONENT_ALIAS(NAME, ...) \
206 namespace tim \
207 { \
208 namespace component \
209 { \
210 using NAME = __VA_ARGS__; \
211 } \
212 }
213#endif
214
215//======================================================================================//
216
217/**
218 * \macro TIMEMORY_PROPERTY_SPECIALIZATION
219 * \brief Specialization of the property specialization
220 */
221
222#if !defined(TIMEMORY_PROPERTY_SPECIALIZATION) && !defined(TIMEMORY_DISABLE_PROPERTIES)
223# define TIMEMORY_PROPERTY_SPECIALIZATION(TYPE, ENUM, ID, ...) \
224 namespace tim \
225 { \
226 namespace component \
227 { \
228 template <> \
229 struct properties<TYPE> : static_properties<TYPE> \
230 { \
231 using type = TYPE; \
232 using value_type = TIMEMORY_COMPONENT; \
233 static constexpr value_type value = ENUM; \
234 static constexpr bool specialized() { return true; } \
235 static const char* enum_string() \
236 { \
237 static const char* _enum = #ENUM; \
238 return static_cast<const char*>(&_enum[9]); \
239 } \
240 static const char* id() { return ID; } \
241 static const idset_t& ids() \
242 { \
243 static auto _instance = []() { \
244 auto _val = idset_t{ ID, __VA_ARGS__ }; \
245 if(_val.find("") != _val.end()) \
246 _val.erase(""); \
247 return _val; \
248 }(); \
249 return _instance; \
250 } \
251 template <typename Archive> \
252 void save(Archive& ar, const unsigned int) const \
253 { \
254 ar(cereal::make_nvp("value", ENUM), \
255 cereal::make_nvp("enum", std::string{ enum_string() }), \
256 cereal::make_nvp("id", std::string{ id() }), \
257 cereal::make_nvp("ids", ids())); \
258 } \
259 template <typename Archive> \
260 void load(Archive&, const unsigned int) \
261 {} \
262 TIMEMORY_COMPONENT operator()() { return ENUM; } \
263 \
264 constexpr operator TIMEMORY_COMPONENT() const { return ENUM; } \
265 }; \
266 template <> \
267 struct enumerator<ENUM> : properties<TYPE> \
268 { \
269 using type = TYPE; \
270 static constexpr bool value = ::tim::trait::is_available<TYPE>::value; \
271 \
272 static constexpr bool specialized() { return true; } \
273 }; \
274 } \
275 }
276#elif !defined(TIMEMORY_PROPERTY_SPECIALIZATION) && defined(TIMEMORY_DISABLE_PROPERTIES)
277# define TIMEMORY_PROPERTY_SPECIALIZATION(...)
278#endif
279
280//======================================================================================//
281
282/**
283 * \macro TIMEMORY_METADATA_SPECIALIZATION
284 * \brief Specialization of the property specialization
285 */
286
287#if !defined(TIMEMORY_METADATA_SPECIALIZATION) && !defined(TIMEMORY_DISABLE_METADATA)
288# define TIMEMORY_METADATA_SPECIALIZATION(TYPE, LABEL, BASIC_DESC, ...) \
289 namespace tim \
290 { \
291 namespace component \
292 { \
293 template <> \
294 struct metadata<TYPE> \
295 { \
296 using type = TYPE; \
297 using value_type = TIMEMORY_COMPONENT; \
298 \
299 static constexpr bool specialized() { return true; } \
300 static constexpr value_type value = properties<TYPE>::value; \
301 static std::string name() { return LABEL; } \
302 static std::string label() { return LABEL; } \
303 static std::string description() { return BASIC_DESC; } \
304 static std::string extra_description() \
305 { \
306 return TIMEMORY_JOIN(" ", __VA_ARGS__); \
307 } \
308 }; \
309 } \
310 }
311#elif !defined(TIMEMORY_METADATA_SPECIALIZATION) && defined(TIMEMORY_DISABLE_METADATA)
312# define TIMEMORY_METADATA_SPECIALIZATION(...)
313#endif
314
315//======================================================================================//
316
317/**
318 * \macro TIMEMORY_TOOLSET_ALIAS
319 * \brief Creates an alias for a complex type when declaring the statistics type
320 */
321
322#if !defined(TIMEMORY_TOOLSET_ALIAS)
323# define TIMEMORY_TOOLSET_ALIAS(NAME, WRAPPER, ...) \
324 namespace tim \
325 { \
326 namespace component \
327 { \
328 namespace aliases \
329 { \
330 using NAME = WRAPPER<__VA_ARGS__>; \
331 } \
332 } \
333 } \
334 using tim::component::aliases::NAME;
335#endif
336
337//======================================================================================//
338//
339// EXTERN TEMPLATE DECLARE AND INSTANTIATE
340//
341//======================================================================================//
342
343#if !defined(_EXTERN_NAME_COMBINE)
344# define _EXTERN_NAME_COMBINE(X, Y) X##Y
345#endif
346//
347//--------------------------------------------------------------------------------------//
348//
349#if !defined(_EXTERN_TUPLE_ALIAS)
350# define _EXTERN_TUPLE_ALIAS(Y) _EXTERN_NAME_COMBINE(extern_tuple_, Y)
351#endif
352//
353//--------------------------------------------------------------------------------------//
354//
355#if !defined(_EXTERN_LIST_ALIAS)
356# define _EXTERN_LIST_ALIAS(Y) _EXTERN_NAME_COMBINE(extern_list_, Y)
357#endif
358
359//--------------------------------------------------------------------------------------//
360
361#if !defined(TIMEMORY_INITIALIZE_STORAGE)
362# define TIMEMORY_INITIALIZE_STORAGE(...) \
363 namespace tim \
364 { \
365 namespace internal \
366 { \
367 namespace initialization \
368 { \
369 namespace \
370 { \
371 using namespace ::tim::component; \
372 namespace component = ::tim::component; \
373 auto _TIM_STORAGE_INIT(__COUNTER__) = \
374 ::tim::storage_initializer::get<__VA_ARGS__>(); \
375 } \
376 } \
377 } \
378 }
379#endif
380
381//--------------------------------------------------------------------------------------//
382// backwards compatibility
383#if !defined(TIMEMORY_STORAGE_INITIALIZER)
384# define TIMEMORY_STORAGE_INITIALIZER(...) TIMEMORY_INITIALIZE_STORAGE(__VA_ARGS__)
385#endif
386
387//--------------------------------------------------------------------------------------//
388//
389#if !defined(TIMEMORY_EXTERN_STORAGE_ALIASES)
390# define TIMEMORY_EXTERN_STORAGE_ALIASES \
391 namespace tim \
392 { \
393 namespace alias \
394 { \
395 template <typename T> \
396 using storage_t = storage<T, typename T::value_type>; \
397 template <typename T> \
398 using storage_impl_t = impl::storage<T, trait::uses_value_storage<T>::value>; \
399 template <typename T> \
400 using storage_deleter_t = impl::storage_deleter<storage_impl_t<T>>; \
401 template <typename T> \
402 using storage_pointer_t = \
403 std::unique_ptr<alias::storage_impl_t<T>, alias::storage_deleter_t<T>>; \
404 } \
405 }
406#endif
407//
408//--------------------------------------------------------------------------------------//
409//
410#if !defined(TIMEMORY_DECLARE_EXTERN_STORAGE)
411# define TIMEMORY_DECLARE_EXTERN_STORAGE(TYPE) \
412 TIMEMORY_EXTERN_STORAGE_ALIASES \
413 namespace tim \
414 { \
415 extern template class impl::storage<TYPE, \
416 trait::uses_value_storage<TYPE>::value>; \
417 extern template class storage<TYPE, typename TYPE::value_type>; \
418 extern template class singleton<alias::storage_impl_t<TYPE>, \
419 alias::storage_pointer_t<TYPE>, TIMEMORY_API>; \
420 extern template storage_singleton<alias::storage_t<TYPE>>* \
421 get_storage_singleton<alias::storage_t<TYPE>>(); \
422 extern template storage_initializer storage_initializer::get<TYPE>(); \
423 namespace node \
424 { \
425 extern template struct data<TYPE>; \
426 extern template struct graph<TYPE>; \
427 extern template struct result<TYPE>; \
428 extern template struct tree<TYPE>; \
429 } \
430 }
431#endif
432//
433//--------------------------------------------------------------------------------------//
434//
435#if !defined(TIMEMORY_INSTANTIATE_EXTERN_STORAGE)
436# define TIMEMORY_INSTANTIATE_EXTERN_STORAGE(TYPE) \
437 TIMEMORY_EXTERN_STORAGE_ALIASES \
438 namespace tim \
439 { \
440 template class impl::storage<TYPE, trait::uses_value_storage<TYPE>::value>; \
441 template class storage<TYPE, typename TYPE::value_type>; \
442 template class singleton<alias::storage_impl_t<TYPE>, \
443 alias::storage_pointer_t<TYPE>, TIMEMORY_API>; \
444 template storage_singleton<alias::storage_t<TYPE>>* \
445 get_storage_singleton<alias::storage_t<TYPE>>(); \
446 template storage_initializer storage_initializer::get<TYPE>(); \
447 namespace node \
448 { \
449 template struct data<TYPE>; \
450 template struct graph<TYPE>; \
451 template struct result<TYPE>; \
452 template struct tree<TYPE>; \
453 } \
454 } \
455 namespace \
456 { \
457 using namespace ::tim::component; \
458 namespace component = ::tim::component; \
459 auto _TIM_STORAGE_INIT(__COUNTER__) = ::tim::storage_initializer::get<TYPE>(); \
460 }
461#endif
462
463//======================================================================================//
464//
465// EXTERN OPERATION DECLARE AND INSTANTIATE
466//
467//======================================================================================//
468//
469#if !defined(TIMEMORY_DECLARE_EXTERN_OPERATIONS)
470# define TIMEMORY_DECLARE_EXTERN_OPERATIONS(TYPE, HAS_DATA) \
471 namespace tim \
472 { \
473 namespace component \
474 { \
475 namespace factory \
476 { \
477 extern template opaque get_opaque<TYPE>(); \
478 extern template opaque get_opaque<TYPE>(scope::config); \
479 extern template std::set<size_t> get_typeids<TYPE>(); \
480 } \
481 } \
482 namespace operation \
483 { \
484 namespace internal \
485 { \
486 extern template struct add_secondary<TYPE, trait::secondary_data<TYPE>::value>; \
487 extern template struct serialization_base<TYPE>; \
488 extern template struct serialization<TYPE, is_enabled<TYPE>::value>; \
489 } \
490 extern template struct add_secondary<TYPE>; \
491 extern template struct add_statistics<TYPE>; \
492 extern template struct assemble<TYPE>; \
493 extern template struct audit<TYPE>; \
494 extern template struct cache<TYPE>; \
495 extern template struct cleanup<TYPE>; \
496 extern template struct construct<TYPE>; \
497 extern template struct copy<TYPE>; \
498 extern template struct derive<TYPE>; \
499 extern template struct fini<TYPE>; \
500 extern template struct fini_storage<TYPE>; \
501 extern template struct echo_measurement<TYPE, trait::echo_enabled<TYPE>::value>; \
502 extern template struct extra_serialization<TYPE>; \
503 extern template struct get<TYPE>; \
504 extern template struct get_is_flat<TYPE, true>; \
505 extern template struct get_is_flat<TYPE, false>; \
506 extern template struct get_is_invalid<TYPE, true>; \
507 extern template struct get_is_invalid<TYPE, false>; \
508 extern template struct get_is_on_stack<TYPE, true>; \
509 extern template struct get_is_on_stack<TYPE, false>; \
510 extern template struct get_depth<TYPE, 0>; \
511 extern template struct init<TYPE>; \
512 extern template struct init_storage<TYPE>; \
513 extern template struct is_running<TYPE, true>; \
514 extern template struct is_running<TYPE, false>; \
515 extern template struct minus<TYPE>; \
516 extern template struct plus<TYPE>; \
517 extern template struct pop_node<TYPE>; \
518 extern template struct print<TYPE>; \
519 extern template struct print_header<TYPE>; \
520 extern template struct print_statistics<TYPE>; \
521 extern template struct print_storage<TYPE>; \
522 extern template struct push_node<TYPE>; \
523 extern template struct record<TYPE>; \
524 extern template struct reset<TYPE>; \
525 extern template struct serialization<TYPE>; \
526 extern template struct set_depth_change<TYPE>; \
527 extern template struct set_is_flat<TYPE>; \
528 extern template struct set_is_invalid<TYPE>; \
529 extern template struct set_is_on_stack<TYPE>; \
530 extern template struct set_iterator<TYPE>; \
531 extern template struct set_prefix<TYPE>; \
532 extern template struct set_scope<TYPE>; \
533 extern template struct set_state<TYPE>; \
534 extern template struct set_started<TYPE>; \
535 extern template struct set_stopped<TYPE>; \
536 extern template struct store<TYPE>; \
537 namespace finalize \
538 { \
539 extern template struct dmp_get<TYPE, enabled_value_storage<TYPE>::value>; \
540 extern template struct get<TYPE, enabled_value_storage<TYPE>::value>; \
541 extern template struct merge<TYPE, enabled_value_storage<TYPE>::value>; \
542 extern template struct mpi_get<TYPE, enabled_value_storage<TYPE>::value>; \
543 extern template struct print<TYPE, enabled_value_storage<TYPE>::value>; \
544 extern template struct upc_get<TYPE, enabled_value_storage<TYPE>::value>; \
545 } \
546 } \
547 }
548#endif
549//
550//--------------------------------------------------------------------------------------//
551//
552#if !defined(TIMEMORY_INSTANTIATE_EXTERN_OPERATIONS)
553# define TIMEMORY_INSTANTIATE_EXTERN_OPERATIONS(TYPE, HAS_DATA) \
554 namespace tim \
555 { \
556 namespace component \
557 { \
558 namespace factory \
559 { \
560 template opaque get_opaque<TYPE>(); \
561 template opaque get_opaque<TYPE>(scope::config); \
562 template std::set<size_t> get_typeids<TYPE>(); \
563 } \
564 } \
565 namespace operation \
566 { \
567 namespace internal \
568 { \
569 template struct add_secondary<TYPE, trait::secondary_data<TYPE>::value>; \
570 template struct serialization_base<TYPE>; \
571 template struct serialization<TYPE, is_enabled<TYPE>::value>; \
572 } \
573 template struct add_secondary<TYPE>; \
574 template struct add_statistics<TYPE>; \
575 template struct assemble<TYPE>; \
576 template struct audit<TYPE>; \
577 template struct cache<TYPE>; \
578 template struct cleanup<TYPE>; \
579 template struct construct<TYPE>; \
580 template struct copy<TYPE>; \
581 template struct derive<TYPE>; \
582 template struct echo_measurement<TYPE, trait::echo_enabled<TYPE>::value>; \
583 template struct extra_serialization<TYPE>; \
584 template struct fini<TYPE>; \
585 template struct fini_storage<TYPE>; \
586 template struct get<TYPE>; \
587 template struct get_is_flat<TYPE, true>; \
588 template struct get_is_flat<TYPE, false>; \
589 template struct get_is_invalid<TYPE, true>; \
590 template struct get_is_invalid<TYPE, false>; \
591 template struct get_is_on_stack<TYPE, true>; \
592 template struct get_is_on_stack<TYPE, false>; \
593 template struct get_depth<TYPE, 0>; \
594 template struct init<TYPE>; \
595 template struct init_storage<TYPE>; \
596 template struct is_running<TYPE, true>; \
597 template struct is_running<TYPE, false>; \
598 template struct minus<TYPE>; \
599 template struct plus<TYPE>; \
600 template struct pop_node<TYPE>; \
601 template struct print<TYPE>; \
602 template struct print_header<TYPE>; \
603 template struct print_statistics<TYPE>; \
604 template struct print_storage<TYPE>; \
605 template struct push_node<TYPE>; \
606 template struct record<TYPE>; \
607 template struct reset<TYPE>; \
608 template struct serialization<TYPE>; \
609 template struct set_depth_change<TYPE>; \
610 template struct set_is_flat<TYPE>; \
611 template struct set_is_invalid<TYPE>; \
612 template struct set_is_on_stack<TYPE>; \
613 template struct set_iterator<TYPE>; \
614 template struct set_prefix<TYPE>; \
615 template struct set_scope<TYPE>; \
616 template struct set_state<TYPE>; \
617 template struct set_started<TYPE>; \
618 template struct set_stopped<TYPE>; \
619 template struct store<TYPE>; \
620 namespace finalize \
621 { \
622 template struct dmp_get<TYPE, enabled_value_storage<TYPE>::value>; \
623 template struct get<TYPE, enabled_value_storage<TYPE>::value>; \
624 template struct merge<TYPE, enabled_value_storage<TYPE>::value>; \
625 template struct mpi_get<TYPE, enabled_value_storage<TYPE>::value>; \
626 template struct print<TYPE, enabled_value_storage<TYPE>::value>; \
627 template struct upc_get<TYPE, enabled_value_storage<TYPE>::value>; \
628 } \
629 } \
630 }
631#endif
632
633//======================================================================================//
634
635#if defined(TIMEMORY_COMPONENT_SOURCE)
636//
637//--------------------------------------------------------------------------------------//
638//
639# if !defined(TIMEMORY_EXTERN_OPERATIONS)
640# define TIMEMORY_EXTERN_OPERATIONS(COMPONENT_NAME, HAS_DATA) \
641 TIMEMORY_INSTANTIATE_EXTERN_OPERATIONS(TIMEMORY_ESC(COMPONENT_NAME), HAS_DATA)
642# endif
643//
644//--------------------------------------------------------------------------------------//
645//
646# if !defined(TIMEMORY_EXTERN_STORAGE)
647# define TIMEMORY_EXTERN_STORAGE(...) \
648 TIMEMORY_INSTANTIATE_EXTERN_STORAGE(__VA_ARGS__)
649# endif
650//
651//--------------------------------------------------------------------------------------//
652//
653# if !defined(TIMEMORY_EXTERN_TEMPLATE)
654# define TIMEMORY_EXTERN_TEMPLATE(...) template __VA_ARGS__;
655# endif
656//
657//--------------------------------------------------------------------------------------//
658//
659#elif defined(TIMEMORY_USE_COMPONENT_EXTERN)
660//
661//--------------------------------------------------------------------------------------//
662//
663# if !defined(TIMEMORY_EXTERN_OPERATIONS)
664# define TIMEMORY_EXTERN_OPERATIONS(COMPONENT_NAME, HAS_DATA) \
665 TIMEMORY_DECLARE_EXTERN_OPERATIONS(TIMEMORY_ESC(COMPONENT_NAME), HAS_DATA)
666# endif
667//
668//--------------------------------------------------------------------------------------//
669//
670# if !defined(TIMEMORY_EXTERN_STORAGE)
671# define TIMEMORY_EXTERN_STORAGE(...) TIMEMORY_DECLARE_EXTERN_STORAGE(__VA_ARGS__)
672# endif
673//
674//--------------------------------------------------------------------------------------//
675//
676# if !defined(TIMEMORY_EXTERN_TEMPLATE)
677# define TIMEMORY_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
678# endif
679//
680//--------------------------------------------------------------------------------------//
681//
682#else
683//
684//--------------------------------------------------------------------------------------//
685//
686# if !defined(TIMEMORY_EXTERN_OPERATIONS)
687# define TIMEMORY_EXTERN_OPERATIONS(...)
688# endif
689//
690//--------------------------------------------------------------------------------------//
691//
692# if !defined(TIMEMORY_EXTERN_STORAGE)
693# define TIMEMORY_EXTERN_STORAGE(...)
694# endif
695//
696//--------------------------------------------------------------------------------------//
697//
698# if !defined(TIMEMORY_EXTERN_TEMPLATE)
699# define TIMEMORY_EXTERN_TEMPLATE(...)
700# endif
701//
702//--------------------------------------------------------------------------------------//
703//
704#endif
705
706//======================================================================================//
707
708#if !defined(TIMEMORY_EXTERN_COMPONENT)
709# define TIMEMORY_EXTERN_COMPONENT(NAME, HAS_DATA, ...) \
710 TIMEMORY_EXTERN_TEMPLATE( \
711 struct tim::component::base<TIMEMORY_ESC(tim::component::NAME), \
712 __VA_ARGS__>) \
713 TIMEMORY_EXTERN_OPERATIONS(TIMEMORY_ESC(component::NAME), HAS_DATA) \
714 TIMEMORY_EXTERN_STORAGE(TIMEMORY_ESC(component::NAME))
715#endif
716
717//======================================================================================//
718
719#if !defined(TIMEMORY_DECLARE_EXTERN_COMPONENT)
720# define TIMEMORY_DECLARE_EXTERN_COMPONENT(NAME, HAS_DATA, ...) \
721 TIMEMORY_DECLARE_EXTERN_TEMPLATE( \
722 struct tim::component::base<TIMEMORY_ESC(tim::component::NAME), \
723 __VA_ARGS__>) \
724 TIMEMORY_DECLARE_EXTERN_OPERATIONS(TIMEMORY_ESC(component::NAME), HAS_DATA) \
725 TIMEMORY_DECLARE_EXTERN_STORAGE(TIMEMORY_ESC(component::NAME))
726#endif
727
728//======================================================================================//
729
730#if !defined(TIMEMORY_INSTANTIATE_EXTERN_COMPONENT)
731# define TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(NAME, HAS_DATA, ...) \
732 TIMEMORY_INSTANTIATE_EXTERN_TEMPLATE( \
733 struct tim::component::base<TIMEMORY_ESC(tim::component::NAME), \
734 __VA_ARGS__>) \
735 TIMEMORY_INSTANTIATE_EXTERN_OPERATIONS(TIMEMORY_ESC(component::NAME), HAS_DATA) \
736 TIMEMORY_INSTANTIATE_EXTERN_STORAGE(TIMEMORY_ESC(component::NAME))
737#endif
738
739//======================================================================================//