SST 12.1.0
Structural Simulation Toolkit
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/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
34namespace SST {
35class Component;
36class Module;
37class SubComponent;
38class BaseComponent;
39namespace Partition {
40class SSTPartitioner;
41}
42namespace Statistics {
43template <class T>
44class Statistic;
45class StatisticBase;
46} // namespace Statistics
47class RankInfo;
48class SSTElementPythonModule;
49
50/****************************************************
51 Base classes for templated documentation classes
52*****************************************************/
53
54namespace ELI {
55
56template <class T>
58{
59public:
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
83private:
84 static std::unique_ptr<std::map<std::string, std::map<std::string, T*>>> infos_;
85};
86template <class T>
87std::unique_ptr<std::map<std::string, std::map<std::string, T*>>> DataBase<T>::infos_;
88
89template <class Policy, class... Policies>
90class BuilderInfoImpl : public Policy, public BuilderInfoImpl<Policies...>
91{
92 using Parent = BuilderInfoImpl<Policies...>;
93
94public:
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
117template <>
119{
120protected:
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
132template <class Base, class T>
134{
135 static bool isLoaded() { return loaded; }
136
137 static const bool loaded;
138};
139
140template <class Base>
142{
143public:
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
173private:
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
181template <class Base>
183{
184public:
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
218private:
219 // Database - needs to be a pointer for static init order
220 static Map* libraries;
221};
222
223template <class Base>
224typename InfoLibraryDatabase<Base>::Map* InfoLibraryDatabase<Base>::libraries = nullptr;
225
226template <class Base, class Info>
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
241private:
242 std::string elemlib_;
243 std::string elem_;
244 Info* info_;
245};
246
247template <class Base>
248void
249InfoLibrary<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
255template <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};
269template <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
287void force_instantiate_bool(bool b, const char* name);
288
289template <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
312constexpr unsigned
313SST_ELI_getMajorNumberFromVersion(SST_ELI_element_version_extraction ver)
314{
315 return ver.getMajor();
316}
317
318constexpr unsigned
319SST_ELI_getMinorNumberFromVersion(SST_ELI_element_version_extraction ver)
320{
321 return ver.getMinor();
322}
323
324constexpr unsigned
325SST_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