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.
library.cpp
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 #if !defined(TIMEMORY_LIBRARY_SOURCE)
26 # define TIMEMORY_LIBRARY_SOURCE 1
27 #endif
28 
30 #include "timemory/config.hpp"
31 #include "timemory/library.h"
33 #include "timemory/timemory.hpp"
34 #include "timemory/trace.hpp"
35 
36 #include <cstdarg>
37 #include <deque>
38 #include <iostream>
39 #include <stack>
40 #include <unordered_map>
41 #include <unordered_set>
42 #include <vector>
43 
44 using namespace tim::component;
45 
46 //======================================================================================//
47 
48 extern "C"
49 {
52 }
53 
54 //======================================================================================//
55 
58 using toolset_t = typename library_toolset_t::component_type;
59 using region_map_t = std::unordered_map<std::string, std::stack<uint64_t>>;
60 using record_map_t = std::unordered_map<uint64_t, toolset_t>;
61 using component_enum_t = std::vector<TIMEMORY_COMPONENT>;
62 using components_stack_t = std::deque<component_enum_t>;
63 
64 static std::string spacer =
65  "#-------------------------------------------------------------------------#";
66 
67 //--------------------------------------------------------------------------------------//
68 
69 static record_map_t&
70 get_record_map()
71 {
72  static thread_local record_map_t _instance;
73  return _instance;
74 }
75 
76 //--------------------------------------------------------------------------------------//
77 
78 static region_map_t&
79 get_region_map()
80 {
81  static thread_local region_map_t _instance;
82  return _instance;
83 }
84 
85 //--------------------------------------------------------------------------------------//
86 
87 static components_stack_t&
88 get_components_stack()
89 {
90  static auto _leader_tid = std::this_thread::get_id();
91  static components_stack_t _leader_instance;
92  static thread_local components_stack_t _worker_instance = _leader_instance;
93  return (std::this_thread::get_id() == _leader_tid) ? _leader_instance
94  : _worker_instance;
95 }
96 
97 //--------------------------------------------------------------------------------------//
98 // default components to record
99 //
100 inline std::string&
102 {
103  static std::string _instance =
104  tim::get_env<std::string>("TIMEMORY_GLOBAL_COMPONENTS", "wall_clock");
105  return _instance;
106 }
107 
108 //--------------------------------------------------------------------------------------//
109 // current set of components being recorded
110 //
111 inline component_enum_t&
113 {
114  auto& _stack = get_components_stack();
115  if(_stack.empty())
116  {
117  _stack.push_back(
118  tim::enumerate_components(get_default_components(), "TIMEMORY_COMPONENTS"));
119  }
120  return _stack.back();
121 }
122 
123 //--------------------------------------------------------------------------------------//
124 
125 std::array<bool, 2>&
127 {
128  static auto _instance = std::array<bool, 2>({ { false, false } });
129  return _instance;
130 }
131 
132 //--------------------------------------------------------------------------------------//
133 //
134 // timemory symbols
135 //
136 //--------------------------------------------------------------------------------------//
137 
138 extern "C"
139 {
140  //----------------------------------------------------------------------------------//
141  // get a unique id
142  //
143  uint64_t timemory_get_unique_id(void)
144  {
145  // the maps are thread-local so no concerns for data-race here since
146  // two threads updating at once and subsequently losing once of the updates
147  // still results in a unique id for that thread
148  static uint64_t uniqID = 0;
149  return uniqID++;
150  }
151 
152  //----------------------------------------------------------------------------------//
153  // create a toolset of measurements
154  //
155  void timemory_create_record(const char* name, uint64_t* id, int n, int* ctypes)
156  {
158  {
159  (*timemory_create_function)(name, id, n, ctypes);
160  return;
161  }
162  // else: provide default behavior
163 
164  static thread_local auto& _record_map = get_record_map();
165  *id = timemory_get_unique_id();
166  _record_map.insert({ *id, toolset_t(name, true) });
167  tim::initialize(_record_map[*id], n, ctypes);
168  _record_map[*id].start();
169  if(_record_map.bucket_count() > _record_map.size())
170  _record_map.rehash(_record_map.size() + 10);
171  }
172 
173  //----------------------------------------------------------------------------------//
174  // destroy a toolset of measurements
175  //
176  void timemory_delete_record(uint64_t id)
177  {
179  {
180  (*timemory_delete_function)(id);
181  }
182  else if(get_record_map().find(id) != get_record_map().end())
183  {
184  static thread_local auto& _record_map = get_record_map();
185  // stop recording, destroy objects, and erase key from map
186  _record_map[id].stop();
187  _record_map.erase(id);
188  }
189  }
190 
191  //----------------------------------------------------------------------------------//
192  //
193  //
195 
196  //----------------------------------------------------------------------------------//
197  //
198  //
200  {
201  if(name)
202  {
203  char* _name[1] = { name };
204  timemory_init_library(1, _name);
205  }
206  }
207 
208  //----------------------------------------------------------------------------------//
209  // initialize the library
210  //
211  void timemory_init_library(int argc, char** argv)
212  {
214  if(get_library_state()[0])
215  return;
216  get_library_state()[0] = true;
217 
218  if(argc < 1 && argv)
219  argc = 1;
220  if(argv == nullptr)
221  {
222  argc = 0;
223  }
224  else
225  {
226  int i = 0;
227  for(; i < argc; ++i)
228  {
229  if(argv[i] == nullptr)
230  {
231  argc = i;
232  break;
233  }
234  }
235  }
236 
237  if(tim::settings::verbose() > 0)
238  {
239  printf("%s\n", spacer.c_str());
240  printf("\tInitialization of timemory library...\n");
241  printf("%s\n\n", spacer.c_str());
242  }
243 
244  if(argc > 0 && argv)
245  tim::timemory_init(argc, argv);
246  tim::manager::instance()->update_metadata_prefix();
247  // tim::settings::parse();
248  }
249 
250  //----------------------------------------------------------------------------------//
251  // finalize the library
253  {
255  get_library_state()[1] = true;
256 
257  auto _manager = tim::manager::master_instance();
259  if(!_manager || !_settings)
260  return;
261 
262  if(_settings->get_enabled() == false && get_record_map().empty())
263  return;
264 
265  auto& _record_map = get_record_map();
266 
267  if(_settings->get_verbose() > 0)
268  {
269  printf("\n%s\n", spacer.c_str());
270  printf("\tFinalization of timemory library...\n");
271  printf("%s\n\n", spacer.c_str());
272  }
273 
274  // put keys into a set so that a potential LD_PRELOAD for timemory_delete_record
275  // is called and there is not a concern for the map iterator
276  std::unordered_set<uint64_t> keys;
277  for(auto& itr : _record_map)
278  keys.insert(itr.first);
279 
280  // delete all the records
281  for(auto& itr : keys)
283 
284  // clear the map
285  _record_map.clear();
286 
287  // have the manager finalize
289  tim::manager::instance()->finalize();
290 
291  // do the finalization
293 
294  // just in case
295  _settings->get_enabled() = false;
296 
297  // set the finalization state to true
298  tim::dmp::set_finalized(true);
299 
300  // reset manager
301  tim::manager::instance().reset();
302 
303  // PGI and Intel compilers don't respect destruction order
304 #if defined(__PGI) || defined(__INTEL_COMPILER)
305  _settings->get_output() = false;
306 #endif
307  }
308 
309  //----------------------------------------------------------------------------------//
310  // pause the collection
311  //
312  void timemory_pause(void) { tim::settings::enabled() = false; }
313 
314  //----------------------------------------------------------------------------------//
315  // resume the collection
316  //
317  void timemory_resume(void) { tim::settings::enabled() = true; }
318 
319  //----------------------------------------------------------------------------------//
320 
321  void timemory_set_default(const char* _component_string)
322  {
325  tim::get_env<std::string>("TIMEMORY_GLOBAL_COMPONENTS", _component_string);
326  // tim::set_env("TIMEMORY_COMPONENTS", _component_string, 0);
327  static thread_local auto& _stack = get_components_stack();
328  if(_stack.empty())
330  }
331 
332  //----------------------------------------------------------------------------------//
333 
334  void timemory_set_environ(const char* evar, const char* eval, int over, int parse)
335  {
337  if(evar && eval)
338  {
339  tim::set_env(evar, eval, over);
340  if(parse > 0)
342  }
343  }
344 
345  //----------------------------------------------------------------------------------//
346 
347  void timemory_add_components(const char* _component_string)
348  {
350  auto& _stack = get_current_components();
351  for(auto itr : tim::enumerate_components(_component_string))
352  _stack.push_back(itr);
353  }
354 
355  //----------------------------------------------------------------------------------//
356 
357  void timemory_remove_components(const char* _component_string)
358  {
360  auto& _stack = get_current_components();
361  for(auto itr : tim::enumerate_components(_component_string))
362  _stack.erase(std::remove(_stack.begin(), _stack.end(), itr), _stack.end());
363  }
364 
365  //----------------------------------------------------------------------------------//
366 
367  void timemory_push_components(const char* _component_string)
368  {
370  static thread_local auto& _stack = get_components_stack();
371  _stack.push_back(tim::enumerate_components(_component_string));
372  }
373 
374  //----------------------------------------------------------------------------------//
375 
376  void timemory_push_components_enum(int types, ...)
377  {
379  static thread_local auto& _stack = get_components_stack();
380 
381  component_enum_t comp({ types });
382  va_list args;
383  va_start(args, types);
384  for(int i = 0; i < TIMEMORY_COMPONENTS_END; ++i)
385  {
386  auto enum_arg = va_arg(args, int);
387  if(enum_arg >= TIMEMORY_COMPONENTS_END)
388  break;
389  comp.push_back(enum_arg);
390  }
391  va_end(args);
392 
393  _stack.push_back(comp);
394  }
395 
396  //----------------------------------------------------------------------------------//
397 
399  {
401  static thread_local auto& _stack = get_components_stack();
402  if(_stack.size() > 1)
403  _stack.pop_back();
404  }
405 
406  //----------------------------------------------------------------------------------//
407 
408  void timemory_begin_record(const char* name, uint64_t* id)
409  {
411  if(!lk || tim::settings::enabled() == false)
412  {
413  *id = std::numeric_limits<uint64_t>::max();
414  return;
415  }
416  auto& comp = get_current_components();
417  timemory_create_record(name, id, comp.size(), (int*) (comp.data()));
418 
419 #if defined(DEBUG)
420  if(tim::settings::verbose() > 2)
421  printf("beginning record for '%s' (id = %lli)...\n", name,
422  (long long int) *id);
423 #endif
424  }
425 
426  //----------------------------------------------------------------------------------//
427 
428  void timemory_begin_record_types(const char* name, uint64_t* id, const char* ctypes)
429  {
431  if(!lk || tim::settings::enabled() == false)
432  {
433  *id = std::numeric_limits<uint64_t>::max();
434  return;
435  }
436 
437  auto comp = tim::enumerate_components(std::string(ctypes));
438  timemory_create_record(name, id, comp.size(), (int*) (comp.data()));
439 
440 #if defined(DEBUG)
441  if(tim::settings::verbose() > 2)
442  printf("beginning record for '%s' (id = %lli)...\n", name,
443  (long long int) *id);
444 #endif
445  }
446 
447  //----------------------------------------------------------------------------------//
448 
449  void timemory_begin_record_enum(const char* name, uint64_t* id, ...)
450  {
452  if(!lk || tim::settings::enabled() == false)
453  {
454  *id = std::numeric_limits<uint64_t>::max();
455  return;
456  }
457 
458  component_enum_t comp;
459  va_list args;
460  va_start(args, id);
461  for(int i = 0; i < TIMEMORY_COMPONENTS_END; ++i)
462  {
463  auto enum_arg = va_arg(args, int);
464  if(enum_arg >= TIMEMORY_COMPONENTS_END)
465  break;
466  comp.push_back(enum_arg);
467  }
468  va_end(args);
469 
470  timemory_create_record(name, id, comp.size(), (int*) (comp.data()));
471 
472 #if defined(DEBUG)
473  if(tim::settings::verbose() > 2)
474  printf("beginning record for '%s' (id = %lli)...\n", name,
475  (long long int) *id);
476 #endif
477  }
478 
479  //----------------------------------------------------------------------------------//
480 
481  uint64_t timemory_get_begin_record(const char* name)
482  {
484  if(!lk || tim::settings::enabled() == false)
485  return std::numeric_limits<uint64_t>::max();
486 
487  uint64_t id = 0;
488  auto& comp = get_current_components();
489  timemory_create_record(name, &id, comp.size(), (int*) (comp.data()));
490 
491 #if defined(DEBUG)
492  if(tim::settings::verbose() > 2)
493  printf("beginning record for '%s' (id = %lli)...\n", name,
494  (long long int) id);
495 #endif
496 
497  return id;
498  }
499 
500  //----------------------------------------------------------------------------------//
501 
502  uint64_t timemory_get_begin_record_types(const char* name, const char* ctypes)
503  {
505  if(!lk || tim::settings::enabled() == false)
506  return std::numeric_limits<uint64_t>::max();
507 
508  uint64_t id = 0;
509  auto comp = tim::enumerate_components(std::string(ctypes));
510  timemory_create_record(name, &id, comp.size(), (int*) (comp.data()));
511 
512 #if defined(DEBUG)
513  if(tim::settings::verbose() > 2)
514  printf("beginning record for '%s' (id = %lli)...\n", name,
515  (long long int) id);
516 #endif
517 
518  return id;
519  }
520 
521  //----------------------------------------------------------------------------------//
522 
523  uint64_t timemory_get_begin_record_enum(const char* name, ...)
524  {
526  if(!lk || tim::settings::enabled() == false)
527  return std::numeric_limits<uint64_t>::max();
528 
529  uint64_t id = 0;
530 
531  component_enum_t comp;
532  va_list args;
533  va_start(args, name);
534  for(int i = 0; i < TIMEMORY_COMPONENTS_END; ++i)
535  {
536  auto enum_arg = va_arg(args, int);
537  if(enum_arg >= TIMEMORY_COMPONENTS_END)
538  break;
539  comp.push_back(enum_arg);
540  }
541  va_end(args);
542 
543  timemory_create_record(name, &id, comp.size(), (int*) (comp.data()));
544 
545 #if defined(DEBUG)
546  if(tim::settings::verbose() > 2)
547  printf("beginning record for '%s' (id = %lli)...\n", name,
548  (long long int) id);
549 #endif
550 
551  return id;
552  }
553 
554  //----------------------------------------------------------------------------------//
555 
556  void timemory_end_record(uint64_t id)
557  {
559  if(!lk || id == std::numeric_limits<uint64_t>::max())
560  return;
561 
563 
564 #if defined(DEBUG)
565  if(tim::settings::verbose() > 2)
566  printf("ending record for %lli...\n", (long long int) id);
567 #endif
568  }
569 
570  //----------------------------------------------------------------------------------//
571 
572  void timemory_push_region(const char* name)
573  {
575  if(!lk)
576  return;
577  auto& region_map = get_region_map();
578  lk.release();
579  auto idx = timemory_get_begin_record(name);
581  region_map[name].push(idx);
582  }
583 
584  //----------------------------------------------------------------------------------//
585 
586  void timemory_pop_region(const char* name)
587  {
589  if(!lk)
590  return;
591  auto& region_map = get_region_map();
592  auto itr = region_map.find(name);
593  if(itr == region_map.end() || (itr != region_map.end() && itr->second.empty()))
594  fprintf(stderr, "Warning! region '%s' does not exist!\n", name);
595  else
596  {
597  uint64_t idx = itr->second.top();
598  lk.release();
599  timemory_end_record(idx);
601  itr->second.pop();
602  }
603  }
604 
605  //==================================================================================//
606  //
607  // Symbols for Fortran
608  //
609  //==================================================================================//
610 
611  void timemory_create_record_(const char* name, uint64_t* id, int n, int* ct)
612  {
613  timemory_create_record(name, id, n, ct);
614  }
615 
617 
618  void timemory_init_library_(int argc, char** argv)
619  {
621  }
622 
624 
626  {
628  }
629 
631  {
633  }
634 
636 
637  void timemory_begin_record_(const char* name, uint64_t* id)
638  {
639  timemory_begin_record(name, id);
640  }
641 
642  void timemory_begin_record_types_(const char* name, uint64_t* id, const char* ctypes)
643  {
644  timemory_begin_record_types(name, id, ctypes);
645  }
646 
647  uint64_t timemory_get_begin_record_(const char* name)
648  {
649  return timemory_get_begin_record(name);
650  }
651 
652  uint64_t timemory_get_begin_record_types_(const char* name, const char* ctypes)
653  {
654  return timemory_get_begin_record_types(name, ctypes);
655  }
656 
657  void timemory_end_record_(uint64_t id) { return timemory_end_record(id); }
658 
659  void timemory_push_region_(const char* name) { return timemory_push_region(name); }
660 
661  void timemory_pop_region_(const char* name) { return timemory_pop_region(name); }
662 
663  //======================================================================================//
664 
665 } // extern "C"
static pointer_t instance()
Get a shared pointer to the instance for the current thread.
static pointer_t master_instance()
Get a shared pointer to the instance on the primary thread.
void(* timemory_delete_func_t)(uint64_t)
function pointer type for timemory_delete_function
Definition: library.h:338
void(* timemory_create_func_t)(const char *, uint64_t *, int, int *)
Definition: library.h:334
#define TIMEMORY_COMPONENTS_END
Definition: enum.h:150
void timemory_pause(void)
Turn off timemory collection.
Definition: library.cpp:312
void timemory_init_library_(int argc, char **argv)
Definition: library.cpp:618
void timemory_push_components_enum(int types,...)
Replace the current set of components with a new set of components with the set of enumerations provi...
Definition: library.cpp:376
void timemory_create_record(const char *name, uint64_t *id, int n, int *ctypes)
Definition: library.cpp:155
timemory_create_func_t timemory_create_function
The function pointer to set to customize which components are used by library interface.
Definition: library.cpp:50
void timemory_begin_record_(const char *name, uint64_t *id)
Definition: library.cpp:637
std::unordered_map< uint64_t, toolset_t > record_map_t
Definition: library.cpp:60
timemory_delete_func_t timemory_delete_function
The function pointer to set which deletes an entry created by timemory_create_function.
Definition: library.cpp:51
void timemory_create_record_(const char *name, uint64_t *id, int n, int *ct)
Definition: library.cpp:611
void timemory_set_environ(const char *evar, const char *eval, int over, int parse)
Definition: library.cpp:334
uint64_t timemory_get_unique_id(void)
Returns a unique integer for a thread.
Definition: library.cpp:143
void timemory_push_region(const char *name)
Definition: library.cpp:572
void timemory_delete_record(uint64_t id)
Deletes the record created by timemory_create_record.
Definition: library.cpp:176
void timemory_end_record(uint64_t id)
Definition: library.cpp:556
uint64_t timemory_get_begin_record_types(const char *name, const char *ctypes)
Variant to timemory_begin_record_types which returns a unique integer.
Definition: library.cpp:502
std::string string_t
Definition: library.cpp:56
component_enum_t & get_current_components()
Definition: library.cpp:112
std::unordered_map< std::string, std::stack< uint64_t > > region_map_t
Definition: library.cpp:59
uint64_t timemory_get_begin_record_enum(const char *name,...)
Variant to timemory_begin_record_enum which returns a unique integer.
Definition: library.cpp:523
void timemory_begin_record_enum(const char *name, uint64_t *id,...)
Similar to timemory_begin_record but accepts a specific enumerated set of components,...
Definition: library.cpp:449
void timemory_pop_components(void)
Inverse of the last timemory_push_components or timemory_push_components_enum call....
Definition: library.cpp:398
void timemory_pop_components_(void)
Definition: library.cpp:635
void timemory_add_components(const char *_component_string)
Add some components to the current set of components being collected Any components which are current...
Definition: library.cpp:347
void timemory_set_default_(const char *components)
Definition: library.cpp:625
void timemory_pop_region(const char *name)
Definition: library.cpp:586
bool timemory_library_is_initialized(void)
Returns whether the library is initialized or not.
Definition: library.cpp:194
void timemory_resume(void)
Turn on timemory collection.
Definition: library.cpp:317
void timemory_begin_record_types_(const char *name, uint64_t *id, const char *ctypes)
Definition: library.cpp:642
std::string & get_default_components()
Definition: library.cpp:101
void timemory_init_library(int argc, char **argv)
Initializes timemory. Not strictly necessary but highly recommended.
Definition: library.cpp:211
std::vector< TIMEMORY_COMPONENT > component_enum_t
Definition: library.cpp:61
std::array< bool, 2 > & get_library_state()
Definition: library.cpp:126
void timemory_remove_components(const char *_component_string)
Remove some components to the current set of components being collected. Any components which are not...
Definition: library.cpp:357
void timemory_push_region_(const char *name)
Definition: library.cpp:659
uint64_t timemory_get_begin_record_types_(const char *name, const char *ctypes)
Definition: library.cpp:652
void timemory_delete_record_(uint64_t id)
Definition: library.cpp:616
void timemory_finalize_library_(void)
Definition: library.cpp:623
void timemory_push_components(const char *_component_string)
Replace the current set of components with a new set of components.
Definition: library.cpp:367
void timemory_push_components_(const char *components)
Definition: library.cpp:630
uint64_t timemory_get_begin_record_(const char *name)
Definition: library.cpp:647
void timemory_named_init_library(char *name)
Definition: library.cpp:199
void timemory_pop_region_(const char *name)
Definition: library.cpp:661
void timemory_end_record_(uint64_t id)
Definition: library.cpp:657
std::deque< component_enum_t > components_stack_t
Definition: library.cpp:62
void timemory_begin_record_types(const char *name, uint64_t *id, const char *ctypes)
Similar to timemory_begin_record but accepts a specific set of components as a string.
Definition: library.cpp:428
uint64_t timemory_get_begin_record(const char *name)
Variant to timemory_begin_record which returns a unique integer.
Definition: library.cpp:481
void timemory_set_default(const char *_component_string)
Pass in a default set of components to use. Will be overridden by TIMEMORY_COMPONENTS environment var...
Definition: library.cpp:321
void timemory_begin_record(const char *name, uint64_t *id)
Definition: library.cpp:408
void timemory_finalize_library(void)
Finalizes timemory. Output will be generated. Any attempt to store data within timemory storage is un...
Definition: library.cpp:252
typename library_toolset_t::component_type toolset_t
Definition: library.cpp:58
TIMEMORY_LIBRARY_TYPE library_toolset_t
Definition: library.cpp:57
A lightweight synchronization object for preventing recursion. The first template parameter should ha...
Definition: trace.hpp:135
void set_env(const std::string &env_var, const Tp &_val, int override)
void timemory_finalize()
finalization of the specified types
void initialize(CompList< CompTypes... > &obj, std::initializer_list< EnumT > components)
Definition: initialize.hpp:53
std::vector< TIMEMORY_COMPONENT > enumerate_components(const Container< StringT, ExtraArgs... > &component_names)
description: use this function to generate an array of enumerations from a list of string that can be...
Definition: enumerate.hpp:62
void timemory_init(Args &&... _args)
Definition: declaration.hpp:49
char ** argv
Definition: definition.hpp:59
char argparse::argument_parser tim::settings * _settings
Definition: definition.hpp:277
tim::mpl::apply< std::string > string
Definition: macros.hpp:52
components
Definition: settings.cpp:1394
static void parse(settings *=instance< TIMEMORY_API >())
Definition: settings.cpp:340
static settings * instance()
Definition: settings.hpp:502
#define TIMEMORY_LIBRARY_TYPE
Definition: types.hpp:270