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