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