SST  15.1.0
StructuralSimulationToolkit
elementinfo.h
1 // Copyright 2009-2025 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2025, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_ELI_ELEMENTINFO_H
13 #define SST_CORE_ELI_ELEMENTINFO_H
14 
15 #include "sst/core/eli/attributeInfo.h"
16 #include "sst/core/eli/categoryInfo.h"
17 #include "sst/core/eli/checkpointableInfo.h"
18 #include "sst/core/eli/defaultInfo.h"
19 #include "sst/core/eli/elementbuilder.h"
20 #include "sst/core/eli/elibase.h"
21 #include "sst/core/eli/interfaceInfo.h"
22 #include "sst/core/eli/paramsInfo.h"
23 #include "sst/core/eli/portsInfo.h"
24 #include "sst/core/eli/profilePointInfo.h"
25 #include "sst/core/eli/simpleInfo.h"
26 #include "sst/core/eli/statsInfo.h"
27 #include "sst/core/eli/subcompSlotInfo.h"
28 #include "sst/core/sst_types.h"
29 #include "sst/core/warnmacros.h"
30 
31 #include <map>
32 #include <string>
33 #include <vector>
34 
35 namespace SST {
36 class Component;
37 class Module;
38 class SubComponent;
39 class BaseComponent;
40 class RealTimeAction;
41 namespace Partition {
42 class SSTPartitioner;
43 }
44 namespace Statistics {
45 template <class T>
46 class Statistic;
47 class StatisticBase;
48 } // namespace Statistics
49 class RankInfo;
51 
52 /****************************************************
53  Base classes for templated documentation classes
54 *****************************************************/
55 
56 namespace ELI {
57 
58 template <class T>
59 class DataBase
60 {
61 public:
62  static T* get(const std::string& elemlib, const std::string& elem)
63  {
64  auto libiter = infos().find(elemlib);
65  if ( libiter != infos().end() ) {
66  auto& submap = libiter->second;
67  auto elemiter = submap.find(elem);
68  if ( elemiter != submap.end() ) {
69  return elemiter->second;
70  }
71  }
72  return nullptr;
73  }
74 
75  static void add(const std::string& elemlib, const std::string& elem, T* info) { infos()[elemlib][elem] = info; }
76 
77 private:
78  static std::map<std::string, std::map<std::string, T*>>& infos()
79  {
80  static std::map<std::string, std::map<std::string, T*>> infos_;
81  return infos_;
82  }
83 };
84 
85 template <class Policy, class... Policies>
86 class BuilderInfoImpl : public Policy, public BuilderInfoImpl<Policies...>
87 {
88  using Parent = BuilderInfoImpl<Policies...>;
89 
90 public:
91  template <class... Args>
92  BuilderInfoImpl(const std::string& elemlib, const std::string& elem, Args&&... args) :
93  Policy(args...),
94  Parent(elemlib, elem, args...) // forward as l-values
95  {
96  DataBase<Policy>::add(elemlib, elem, this);
97  }
98 
99  template <class XMLNode>
100  void outputXML(XMLNode* node)
101  {
102  Policy::outputXML(node);
103  Parent::outputXML(node);
104  }
105 
106  void toString(std::ostream& os) const
107  {
108  Policy::toString(os);
109  Parent::toString(os);
110  }
111 
112  BuilderInfoImpl(const BuilderInfoImpl&) = delete;
113  BuilderInfoImpl& operator=(const BuilderInfoImpl&) = delete;
114 };
115 
116 template <>
117 class BuilderInfoImpl<void>
118 {
119 protected:
120  template <class... Args>
121  explicit BuilderInfoImpl(Args&&... UNUSED(args))
122  {}
123 
124  template <class XMLNode>
125  void outputXML(XMLNode* UNUSED(node))
126  {}
127 
128  void toString(std::ostream& UNUSED(os)) const {}
129 
130  BuilderInfoImpl(const BuilderInfoImpl&) = delete;
131  BuilderInfoImpl& operator=(const BuilderInfoImpl&) = delete;
132 };
133 
134 template <class Base>
136 {
137 public:
138  using BaseInfo = typename Base::BuilderInfo;
139 
140  explicit InfoLibrary(const std::string& name) :
141  name_(name)
142  {}
143 
144  BaseInfo* getInfo(const std::string& name)
145  {
146  auto iter = infos_.find(name);
147  if ( iter == infos_.end() ) {
148  return nullptr;
149  }
150  else {
151  return iter->second;
152  }
153  }
154 
155  bool hasInfo(const std::string& name) const { return infos_.find(name) != infos_.end(); }
156 
157  int numEntries(bool exclude_aliases = false) const
158  {
159  if ( !exclude_aliases ) return infos_.size();
160  int count = 0;
161  for ( auto x : infos_ ) {
162  if ( x.first != x.second->getAlias() ) ++count;
163  }
164  return count;
165  }
166 
167  const std::map<std::string, BaseInfo*>& getMap() const { return infos_; }
168 
169  void readdInfo(const std::string& name, BaseInfo* info)
170  {
171  infos_[name] = info;
172 
173  // Add the alias
174  const std::string& alias = info->getAlias();
175  if ( !alias.empty() ) infos_[alias] = info;
176  }
177 
178  bool addInfo(const std::string& elem, BaseInfo* info)
179  {
180  readdInfo(elem, info);
181  // dlopen might thrash this later - add a loader to put it back in case
182  addLoader(name_, elem, info);
183  return true;
184  }
185 
186 private:
187  void addLoader(const std::string& lib, const std::string& name, BaseInfo* info);
188 
189  std::map<std::string, BaseInfo*> infos_;
190 
191  std::string name_;
192 };
193 
194 template <class Base>
196 {
197 public:
198  using Library = InfoLibrary<Base>;
199  using BaseInfo = typename Library::BaseInfo;
200  using Map = std::map<std::string, Library*>;
201 
202  static std::vector<std::string> getRegisteredElementNames()
203  {
204  // Need to pull out all the elements from the libraries that
205  // have an element of this type
206 
207  std::vector<std::string> ret;
208  // First iterate over libraries
209  for ( auto& [name, lib] : libraries() ) {
210  for ( auto& [elemlib, info] : lib->getMap() ) {
211  ret.push_back(name + "." + elemlib);
212  }
213  }
214  return ret;
215  }
216 
217  static Library* getLibrary(const std::string& name)
218  {
219  auto& lib = libraries()[name];
220  if ( !lib ) lib = new Library(name);
221  return lib;
222  }
223 
224 private:
225  // Database
226  static Map& libraries()
227  {
228  static Map libs;
229  return libs;
230  }
231 };
232 
233 template <class Base, class Info>
234 struct InfoLoader : public LibraryLoader
235 {
236  InfoLoader(const std::string& elemlib, const std::string& elem, Info* info) :
237  elemlib_(elemlib),
238  elem_(elem),
239  info_(info)
240  {}
241 
242  void load() override
243  {
244  auto* lib = InfoLibraryDatabase<Base>::getLibrary(elemlib_);
245  if ( !lib->hasInfo(elem_) ) {
246  lib->readdInfo(elem_, info_);
247  }
248  }
249 
250 private:
251  std::string elemlib_;
252  std::string elem_;
253  Info* info_;
254 
255  InfoLoader(const InfoLoader&) = delete;
256  InfoLoader& operator=(const InfoLoader&) = delete;
257 };
258 
259 template <class Base>
260 void
261 InfoLibrary<Base>::addLoader(const std::string& elemlib, const std::string& elem, BaseInfo* info)
262 {
263  auto loader = new InfoLoader<Base, BaseInfo>(elemlib, elem, info);
264  LoadedLibraries::addLoader(elemlib, elem, info->getAlias(), loader);
265 }
266 
267 template <class Base>
269 {
270  static InfoLibrary<Base>* getLibrary(const std::string& name)
271  {
273  }
274 
275  template <class T>
276  static bool add()
277  {
278  return Base::template addDerivedInfo<T>(T::ELI_getLibrary(), T::ELI_getName());
279  }
280 };
281 
282 template <class Base, class T>
284 {
285  static bool isLoaded() { return loaded; }
286 
287  static inline const bool loaded = ElementsInfo<Base>::template add<T>();
288 };
289 
291 {
292  template <class T>
293  static InfoLibrary<T>* getLibrary(const std::string& name)
294  {
296  }
297 
298  template <class T>
299  static std::vector<std::string> getRegisteredElementNames()
300  {
302  }
303 };
304 
305 void force_instantiate_bool(bool b, const char* name);
306 
307 template <class T>
309 {
310  static bool ELI_isLoaded() { return T::ELI_isLoaded(); }
311 };
312 
313 } // namespace ELI
314 
315 /**************************************************************************
316  Class and constexpr functions to extract integers from version number.
317 **************************************************************************/
318 
320 {
321  const unsigned major;
322  const unsigned minor;
323  const unsigned tertiary;
324 
325  constexpr unsigned getMajor() const { return major; }
326  constexpr unsigned getMinor() const { return minor; }
327  constexpr unsigned getTertiary() const { return tertiary; }
328 };
329 
330 constexpr unsigned
331 SST_ELI_getMajorNumberFromVersion(SST_ELI_element_version_extraction ver)
332 {
333  return ver.getMajor();
334 }
335 
336 constexpr unsigned
337 SST_ELI_getMinorNumberFromVersion(SST_ELI_element_version_extraction ver)
338 {
339  return ver.getMinor();
340 }
341 
342 constexpr unsigned
343 SST_ELI_getTertiaryNumberFromVersion(SST_ELI_element_version_extraction ver)
344 {
345  return ver.getTertiary();
346 }
347 
348 /**************************************************************************
349  Macros used by elements to add element documentation
350 **************************************************************************/
351 
352 #define SST_ELI_DECLARE_INFO(...) \
353  using BuilderInfo = ::SST::ELI::BuilderInfoImpl<__VA_ARGS__, SST::ELI::ProvidesDefaultInfo, void>; \
354  static bool addInfo(const std::string& elemlib, const std::string& elem, BuilderInfo* info) \
355  { \
356  return ::SST::ELI::InfoDatabase::getLibrary<__LocalEliBase>(elemlib)->addInfo(elem, info); \
357  } \
358  SST_ELI_DECLARE_INFO_COMMON()
359 
360 #define SST_ELI_DECLARE_DEFAULT_INFO() \
361  using BuilderInfo = ::SST::ELI::BuilderInfoImpl<SST::ELI::ProvidesDefaultInfo, void>; \
362  template <class BuilderImpl> \
363  static bool addInfo(const std::string& elemlib, const std::string& elem, BuilderImpl* info) \
364  { \
365  return ::SST::ELI::InfoDatabase::getLibrary<__LocalEliBase>(elemlib)->addInfo(elem, info); \
366  } \
367  SST_ELI_DECLARE_INFO_COMMON()
368 
369 #define SST_ELI_DECLARE_INFO_EXTERN(...) \
370  using BuilderInfo = ::SST::ELI::BuilderInfoImpl<SST::ELI::ProvidesDefaultInfo, __VA_ARGS__, void>; \
371  static bool addInfo(const std::string& elemlib, const std::string& elem, BuilderInfo* info); \
372  SST_ELI_DECLARE_INFO_COMMON()
373 
374 #define SST_ELI_DECLARE_DEFAULT_INFO_EXTERN() \
375  using BuilderInfo = ::SST::ELI::BuilderInfoImpl<SST::ELI::ProvidesDefaultInfo, void>; \
376  static bool addInfo(const std::string& elemlib, const std::string& elem, BuilderInfo* info); \
377  SST_ELI_DECLARE_INFO_COMMON()
378 
379 #define SST_ELI_DEFINE_INFO_EXTERN(base) \
380  bool base::addInfo(const std::string& elemlib, const std::string& elem, BuilderInfo* info) \
381  { \
382  return ::SST::ELI::InfoDatabase::getLibrary<__LocalEliBase>(elemlib)->addInfo(elem, info); \
383  }
384 
385 #define SST_ELI_EXTERN_DERIVED(base, cls, lib, name, version, desc) \
386  bool ELI_isLoaded(); \
387  SST_ELI_DEFAULT_INFO(lib, name, ELI_FORWARD_AS_ONE(version), desc)
388 
389 // The Intel compilers do not correctly instantiate symbols
390 // even though they are required. We have to force the instantiation
391 // in source files, header files are not good enough
392 // we do this by creating a static bool that produces an undefined ref
393 // if the instantiate macro is missing in a source file
394 #ifdef __INTEL_COMPILER
395 #define SST_ELI_FORCE_INSTANTIATION(base, cls) \
396  template <class T> \
397  struct ELI_ForceRegister \
398  { \
399  ELI_ForceRegister() \
400  { \
401  bool b = SST::ELI::InstantiateBuilder<base, cls>::isLoaded() && \
402  SST::ELI::InstantiateBuilderInfo<base, cls>::isLoaded(); \
403  SST::ELI::force_instantiate_bool(b, #cls); \
404  } \
405  }; \
406  ELI_ForceRegister<cls> force_instantiate;
407 // if the implementation is entirely in a C++ file
408 // the Intel compiler will not generate any code because
409 // it none of the symbols can be observed by other files
410 // this forces the Intel compiler to export symbols self-contained in a C++ file
411 #define SST_ELI_EXPORT(cls) template class SST::ELI::ForceExport<cls>;
412 #else
413 #define SST_ELI_FORCE_INSTANTIATION(base, cls)
414 #define SST_ELI_EXPORT(cls)
415 #endif
416 
417 // This call needs to be made for classes that will acually be
418 // instanced, as opposed to only be declared as an API (using
419 // SST_ELI_DECLARE_BASE or SST_ELI_DECLARE_NEW_BASE). This class will
420 // inherit the ELI information from it's parent ELI API classes (the
421 // informatin in the parent APIs will be added to the ELI declared in
422 // this class. Any local information will overwrite any inherited
423 // information. See comment for SST_ELI_DECLARE_BASE in elibase.h for
424 // info on how __EliDerivedLevel is used.
425 #define SST_ELI_REGISTER_DERIVED(base, cls, lib, name, version, desc) \
426  [[maybe_unused]] \
427  static constexpr int __EliDerivedLevel = std::is_same_v<base, cls> ? __EliBaseLevel : __EliBaseLevel + 1; \
428  static bool ELI_isLoaded() \
429  { \
430  return SST::ELI::InstantiateBuilder<base, cls>::isLoaded() && \
431  SST::ELI::InstantiateBuilderInfo<base, cls>::isLoaded(); \
432  } \
433  SST_ELI_FORCE_INSTANTIATION(base, cls) \
434  SST_ELI_DEFAULT_INFO(lib, name, ELI_FORWARD_AS_ONE(version), desc)
435 
436 #define SST_ELI_REGISTER_EXTERN(base, cls) \
437  bool cls::ELI_isLoaded() \
438  { \
439  return SST::ELI::InstantiateBuilder<base, cls>::isLoaded() && \
440  SST::ELI::InstantiateBuilderInfo<base, cls>::isLoaded(); \
441  }
442 
443 } // namespace SST
444 
445 #endif // SST_CORE_ELI_ELEMENTINFO_H
Definition: elementinfo.h:234
Forms the base class for statistics gathering within SST.
Definition: statbase.h:49
Definition: elementinfo.h:283
Definition: action.cc:18
Definition: elementinfo.h:290
Forms the template defined base class for statistics gathering within SST.
Definition: elementinfo.h:46
Definition: elementinfo.h:195
Definition: elementinfo.h:268
Definition: elementinfo.h:86
Definition: elementinfo.h:308
Definition: elibase.h:124
Definition: elementinfo.h:135
Definition: rankInfo.h:23
Definition: elementinfo.h:319
Definition: elementinfo.h:59
Base class for python modules in element libraries.
Definition: element_python.h:132