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