SST 15.0
Structural Simulation Toolkit
factory.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_FACTORY_H
13#define SST_CORE_FACTORY_H
14
15#include "sst/core/eli/elementinfo.h"
16#include "sst/core/output.h"
17#include "sst/core/params.h"
18#include "sst/core/sst_types.h"
19#include "sst/core/sstpart.h"
20
21#include <iostream>
22#include <mutex>
23#include <set>
24#include <stdio.h>
25#include <vector>
26
27/* Forward declare for Friendship */
28extern int main(int argc, char** argv);
29
30namespace SST {
31namespace Statistics {
32class StatisticOutput;
33class StatisticBase;
34} // namespace Statistics
35
36class Module;
37class Component;
38class BaseComponent;
39class SubComponent;
40class ElemLoader;
42
43/**
44 * Class for instantiating Components, Links and the like out
45 * of element libraries.
46 */
47class Factory
48{
49public:
50 static Factory* getFactory() { return instance; }
51
52 /** Get a list of allowed ports for a given component type.
53 * @param type - Name of component in lib.name format
54 * @return True if this is a valid portname
55 */
56 bool isPortNameValid(const std::string& type, const std::string& port_name);
57
58 /** Get a list of allowed param keys for a given component type.
59 * @param type - Name of component in lib.name format
60 * @return Allowed parameter names
61 */
62 const std::vector<std::string>& getParamNames(const std::string& type);
63
64 /** Attempt to create a new Component instantiation
65 * @param id - The unique ID of the component instantiation
66 * @param componentname - The fully qualified elementlibname.componentname type of component
67 * @param params - The params to pass to the component's constructor
68 * @return Newly created component
69 */
70 Component* CreateComponent(ComponentId_t id, const std::string& componentname, Params& params);
71
72 /** Ensure that an element library containing the required event is loaded
73 * @param eventname - The fully qualified elementlibname.eventname type
74 */
75 void RequireEvent(const std::string& eventname);
76
77 bool doesSubComponentExist(const std::string& type);
78
79 /** Return partitioner function
80 * @param name - Fully qualified elementlibname.partitioner type name
81 */
83 const std::string& name, RankInfo total_ranks, RankInfo my_rank, int verbosity);
84
85 /**
86 Check to see if a given element type is loadable with a particular API
87 @param name - Name of element to check in lib.name format
88 @return True if loadable as the API specified as the template parameter
89 */
90 template <class Base>
91 bool isSubComponentLoadableUsingAPI(const std::string& type)
92 {
93 std::string elemlib, elem;
94 std::tie(elemlib, elem) = parseLoadName(type);
95
96 requireLibrary(elemlib);
97 std::lock_guard<std::recursive_mutex> lock(factoryMutex);
98
99 auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
100 if ( lib ) {
101 auto map = lib->getMap();
102 auto* info = lib->getInfo(elem);
103 if ( info ) {
104 auto* builderLib = Base::getBuilderLibrary(elemlib);
105 if ( builderLib ) {
106 auto* fact = builderLib->getBuilder(elem);
107 if ( fact ) {
108 return true;
109 }
110 }
111 }
112 }
113 return false;
114 }
115
116 template <class Base, int index, class InfoType>
117 const InfoType& getSimpleInfo(const std::string& type)
118 {
119 static InfoType invalid_ret;
120 std::string elemlib, elem;
121 std::tie(elemlib, elem) = parseLoadName(type);
122
123 std::stringstream err_os;
124 requireLibrary(elemlib, err_os);
125 std::lock_guard<std::recursive_mutex> lock(factoryMutex);
126
127 auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
128 if ( lib ) {
129 auto* info = lib->getInfo(elem);
130 if ( info ) {
131 // Need to cast this to a ProvidesSimpleInfo to get
132 // the templated data
133 auto* cast_info = dynamic_cast<ELI::ProvidesSimpleInfo<index, InfoType>*>(info);
134 if ( cast_info ) {
135 return cast_info->getSimpleInfo();
136 }
137 }
138 }
139 // notFound(Base::ELI_baseName(), type, err_os.str());
140 return invalid_ret;
141 }
142
143 /**
144 * General function to create a given base class.
145 *
146 * @param type
147 * @param params
148 * @param args Constructor arguments
149 */
150 template <class Base, class... CtorArgs>
151 Base* Create(const std::string& type, CtorArgs&&... args)
152 {
153 std::string elemlib, elem;
154 std::tie(elemlib, elem) = parseLoadName(type);
155
156 std::stringstream err_os;
157 requireLibrary(elemlib, err_os);
158 std::lock_guard<std::recursive_mutex> lock(factoryMutex);
159
160 auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
161 if ( lib ) {
162 auto* info = lib->getInfo(elem);
163 if ( info ) {
164 auto* builderLib = Base::getBuilderLibrary(elemlib);
165 if ( builderLib ) {
166 auto* fact = builderLib->getBuilder(elem);
167 if ( fact ) {
168 Base* ret = fact->create(std::forward<CtorArgs>(args)...);
169 return ret;
170 }
171 }
172 }
173 }
174 notFound(Base::ELI_baseName(), type, err_os.str());
175 return nullptr;
176 }
177
178 template <class T, class... ARGS>
179 T* CreateProfileTool(const std::string& type, ARGS... args)
180 {
181 return Factory::getFactory()->Create<T>(type, args...);
182 }
183
184 /**
185 * General function to create a given base class. This version
186 * should be used if a Params object is being passed in and you
187 * need the system to populate the allowed keys for the object.
188 * If you don't need the allowed keys to be populated, just use
189 * the Create() bunction.
190 *
191 * @param type
192 * @param params
193 * @param args Constructor arguments
194 */
195 template <class Base, class... CtorArgs>
196 Base* CreateWithParams(const std::string& type, SST::Params& params, CtorArgs&&... args)
197 {
198 std::string elemlib, elem;
199 std::tie(elemlib, elem) = parseLoadName(type);
200
201 std::stringstream err_os;
202 requireLibrary(elemlib, err_os);
203 std::lock_guard<std::recursive_mutex> lock(factoryMutex);
204
205 auto* lib = ELI::InfoDatabase::getLibrary<Base>(elemlib);
206 if ( lib ) {
207 auto map = lib->getMap();
208 auto* info = lib->getInfo(elem);
209 if ( info ) {
210 auto* builderLib = Base::getBuilderLibrary(elemlib);
211 if ( builderLib ) {
212 auto* fact = builderLib->getBuilder(elem);
213 if ( fact ) {
214 params.pushAllowedKeys(info->getParamNames());
215 Base* ret = fact->create(std::forward<CtorArgs>(args)...);
216 params.popAllowedKeys();
217 return ret;
218 }
219 }
220 }
221 }
222 notFound(Base::ELI_baseName(), type, err_os.str());
223 return nullptr;
224 }
225
226 /** Instantiate a new Statistic
227 * @param comp - Owning component
228 * @param type - Fully qualified elementlibname.statisticname type
229 * @param statName - Name of the statistic
230 * @param statSubId - Name of the sub statistic
231 * @param params - Parameters to pass to the Statistics's constructor
232 * @param fieldType - Type of data stored in statistic
233 */
234 template <class T, class... Args>
235 Statistics::Statistic<T>* CreateStatistic(const std::string& type, BaseComponent* comp, const std::string& statName,
236 const std::string& stat, Params& params, Args... args)
237 {
238 std::string elemlib, elem;
239 std::tie(elemlib, elem) = parseLoadName(type);
240 // ensure library is already loaded...
241 std::stringstream sstr;
242 requireLibrary(elemlib, sstr);
243
244 auto* lib = ELI::BuilderDatabase::getLibrary<Statistics::Statistic<T>, Args...>(elemlib);
245 if ( lib ) {
246 auto* fact = lib->getFactory(elem);
247 if ( fact ) {
248 return fact->create(comp, statName, stat, params, std::forward<Args>(args)...);
249 }
250 }
251 // If we make it to here, component not found
252 out.fatal(CALL_INFO, -1, "can't find requested statistic %s.\n%s\n", type.c_str(), sstr.str().c_str());
253 return nullptr;
254 }
255
256 /** Return Python Module creation function
257 * @param name - Fully qualified elementlibname.pythonModName type name
258 */
259 SSTElementPythonModule* getPythonModule(const std::string& name);
260
261 /**
262 * @brief hasLibrary Checks to see if library exists and can be loaded
263 * @param elemlib
264 * @param err_os Stream to print error messages to
265 * @return whether the library was found
266 */
267 bool hasLibrary(const std::string& elemlib, std::ostream& err_os);
268 void requireLibrary(const std::string& elemlib, std::ostream& err_os);
269 /**
270 * @brief requireLibrary Throws away error messages
271 * @param elemlib
272 */
273 void requireLibrary(const std::string& elemlib);
274
275 void getLoadedLibraryNames(std::set<std::string>& lib_names);
276 void loadUnloadedLibraries(const std::set<std::string>& lib_names);
277
278 const std::string& getSearchPaths();
279
280 /** Determine if a SubComponentSlot is defined in a components ElementInfoStatistic
281 * @param type - The name of the component/subcomponent
282 * @param slotName - The name of the SubComponentSlot
283 * @return True if the SubComponentSlot is defined in the component's ELI
284 */
285 bool DoesSubComponentSlotExist(const std::string& type, const std::string& slotName);
286
287 /** Determine if a statistic is defined in a components ElementInfoStatistic
288 * @param type - The name of the component
289 * @param statisticName - The name of the statistic
290 * @return True if the statistic is defined in the component's ElementInfoStatistic
291 */
292 bool DoesComponentInfoStatisticNameExist(const std::string& type, const std::string& statisticName);
293
294 const std::vector<std::string>& GetValidStatistics(const std::string& compType);
295
296 /** Get the enable level of a statistic defined in the component's ElementInfoStatistic
297 * @param componentname - The name of the component
298 * @param statisticName - The name of the statistic
299 * @return The Enable Level of the statistic from the ElementInfoStatistic
300 */
301 uint8_t GetComponentInfoStatisticEnableLevel(const std::string& type, const std::string& statisticName);
302
303 /** Get the units of a statistic defined in the component's ElementInfoStatistic
304 * @param componentname - The name of the component
305 * @param statisticName - The name of the statistic
306 * @return The units string of the statistic from the ElementInfoStatistic
307 */
308 std::string GetComponentInfoStatisticUnits(const std::string& type, const std::string& statisticName);
309
310 /** Get a list of allowed ports for a given component type.
311 * @param type - Type of component in lib.name format
312 * @param point = Profile point to check
313 * @return True if this is a valid profile point
314 */
315 bool isProfilePointValid(const std::string& type, const std::string& point);
316
317private:
318 friend int ::main(int argc, char** argv);
319
320 [[noreturn]]
321 void notFound(const std::string& baseName, const std::string& type, const std::string& errorMsg);
322
323 explicit Factory(const std::string& searchPaths);
324 ~Factory();
325
326 Factory(const Factory&) = delete; // Don't Implement
327 Factory& operator=(const Factory&) = delete; // Don't Implement
328
329 static Factory* instance;
330
331 // find library information for name
332 bool findLibrary(const std::string& name, std::ostream& err_os = std::cerr);
333 // handle low-level loading of name
334 bool loadLibrary(const std::string& name, std::ostream& err_os = std::cerr);
335
336 std::set<std::string> loaded_libraries;
337
338 std::string searchPaths;
339
340 ElemLoader* loader;
341 std::string loadingComponentType;
342
343 std::pair<std::string, std::string> parseLoadName(const std::string& wholename);
344
345 std::recursive_mutex factoryMutex;
346
347protected:
348 Output& out;
349};
350
351} // namespace SST
352
353#endif // SST_CORE_FACTORY_H
Main component object for the simulation.
Definition baseComponent.h:62
Main component object for the simulation.
Definition component.h:31
Definition simpleInfo.h:88
Class to load Element Libraries.
Definition elemLoader.h:24
Class for instantiating Components, Links and the like out of element libraries.
Definition factory.h:48
Statistics::Statistic< T > * CreateStatistic(const std::string &type, BaseComponent *comp, const std::string &statName, const std::string &stat, Params &params, Args... args)
Instantiate a new Statistic.
Definition factory.h:235
void RequireEvent(const std::string &eventname)
Ensure that an element library containing the required event is loaded.
Definition factory.cc:487
Partition::SSTPartitioner * CreatePartitioner(const std::string &name, RankInfo total_ranks, RankInfo my_rank, int verbosity)
Return partitioner function.
Definition factory.cc:498
bool DoesSubComponentSlotExist(const std::string &type, const std::string &slotName)
Determine if a SubComponentSlot is defined in a components ElementInfoStatistic.
Definition factory.cc:236
SSTElementPythonModule * getPythonModule(const std::string &name)
Return Python Module creation function.
Definition factory.cc:532
Component * CreateComponent(ComponentId_t id, const std::string &componentname, Params &params)
Attempt to create a new Component instantiation.
Definition factory.cc:198
std::string GetComponentInfoStatisticUnits(const std::string &type, const std::string &statisticName)
Get the units of a statistic defined in the component's ElementInfoStatistic.
Definition factory.cc:383
Base * CreateWithParams(const std::string &type, SST::Params &params, CtorArgs &&... args)
General function to create a given base class.
Definition factory.h:196
bool hasLibrary(const std::string &elemlib, std::ostream &err_os)
hasLibrary Checks to see if library exists and can be loaded
Definition factory.cc:558
uint8_t GetComponentInfoStatisticEnableLevel(const std::string &type, const std::string &statisticName)
Get the enable level of a statistic defined in the component's ElementInfoStatistic.
Definition factory.cc:333
const std::vector< std::string > & getParamNames(const std::string &type)
Get a list of allowed param keys for a given component type.
Definition factory.cc:157
bool isPortNameValid(const std::string &type, const std::string &port_name)
Get a list of allowed ports for a given component type.
Definition factory.cc:100
Base * Create(const std::string &type, CtorArgs &&... args)
General function to create a given base class.
Definition factory.h:151
bool DoesComponentInfoStatisticNameExist(const std::string &type, const std::string &statisticName)
Determine if a statistic is defined in a components ElementInfoStatistic.
Definition factory.cc:321
bool isProfilePointValid(const std::string &type, const std::string &point)
Get a list of allowed ports for a given component type.
Definition factory.cc:418
bool isSubComponentLoadableUsingAPI(const std::string &type)
Check to see if a given element type is loadable with a particular API.
Definition factory.h:91
Module is a tag class used with the loadModule function.
Definition module.h:26
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file.
Definition output.h:54
Parameter store.
Definition params.h:58
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition params.cc:243
void pushAllowedKeys(const std::vector< std::string > &keys)
Definition params.cc:233
Base class for Partitioning graphs.
Definition sstpart.h:32
Definition rankInfo.h:24
Base class for python modules in element libraries.
Definition element_python.h:133
Forms the base class for statistics gathering within SST.
Definition statbase.h:49
Forms the base class for statistics output generation within the SST core.
Definition statoutput.h:52
Forms the template defined base class for statistics gathering within SST.
Definition statbase.h:373
SubComponent is a class loadable through the factory which allows dynamic functionality to be added t...
Definition subcomponent.h:29