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