SST  9.1.0
StructuralSimulationToolkit
elementbuilder.h
1 
2 #ifndef SST_CORE_FACTORY_INFO_H
3 #define SST_CORE_FACTORY_INFO_H
4 
5 #include <sst/core/eli/elibase.h>
6 #include <type_traits>
7 
8 namespace SST {
9 namespace ELI {
10 
11 template <class Base, class... Args>
12 struct Builder
13 {
14  typedef Base* (*createFxn)(Args...);
15 
16  virtual Base* create(Args... ctorArgs) = 0;
17 
18  template <class NewBase>
19  using ChangeBase = Builder<NewBase,Args...>;
20 };
21 
22 template <class Base, class... CtorArgs>
24 {
25  public:
26  using BaseBuilder = Builder<Base,CtorArgs...>;
27 
28  BuilderLibrary(const std::string& name) :
29  name_(name)
30  {
31  }
32 
33  BaseBuilder* getBuilder(const std::string &name) {
34  auto iter = factories_.find(name);
35  if (iter == factories_.end()){
36  return nullptr;
37  } else {
38  return iter->second;
39  }
40  }
41 
42  const std::map<std::string, BaseBuilder*>& getMap() const {
43  return factories_;
44  }
45 
46  void readdBuilder(const std::string& name, BaseBuilder* fact){
47  factories_[name] = fact;
48  }
49 
50  bool addBuilder(const std::string& elem, BaseBuilder* fact){
51  readdBuilder(elem, fact);
52  return addLoader(name_, elem, fact);
53  }
54 
55  template <class NewBase>
56  using ChangeBase = BuilderLibrary<NewBase,CtorArgs...>;
57 
58  private:
59  bool addLoader(const std::string& elemlib, const std::string& elem, BaseBuilder* fact);
60 
61  std::map<std::string, BaseBuilder*> factories_;
62 
63  std::string name_;
64 };
65 
66 template <class Base, class... CtorArgs>
68  public:
69  using Library=BuilderLibrary<Base,CtorArgs...>;
70  using BaseFactory=typename Library::BaseBuilder;
71  using Map=std::map<std::string,Library*>;
72 
73  static Library* getLibrary(const std::string& name){
74  if (!libraries){
75  libraries = new std::map<std::string,Library*>;
76  }
77  auto iter = libraries->find(name);
78  if (iter == libraries->end()){
79  auto* info = new Library(name);
80  (*libraries)[name] = info;
81  return info;
82  } else {
83  return iter->second;
84  }
85  }
86 
87  template <class NewBase>
88  using ChangeBase = BuilderLibraryDatabase<NewBase,CtorArgs...>;
89 
90  private:
91  // Database - needs to be a pointer for static init order
92  static Map* libraries;
93 };
94 
95 template <class Base, class... CtorArgs> typename BuilderLibraryDatabase<Base,CtorArgs...>::Map*
96  BuilderLibraryDatabase<Base,CtorArgs...>::libraries = nullptr;
97 
98 template <class Base, class Builder, class... CtorArgs>
99 struct BuilderLoader : public LibraryLoader {
100  BuilderLoader(const std::string& elemlib,
101  const std::string& elem,
102  Builder* builder) :
103  elemlib_(elemlib), elem_(elem), builder_(builder)
104  {
105  }
106 
107  void load() override {
109  ->readdBuilder(elem_,builder_);
110  }
111 
112  private:
113  std::string elemlib_;
114  std::string elem_;
115  Builder* builder_;
116 };
117 
118 template <class Base, class... CtorArgs>
119 bool BuilderLibrary<Base,CtorArgs...>::addLoader(const std::string &elemlib, const std::string &elem,
120  BaseBuilder *fact){
121  auto loader = new BuilderLoader<Base,BaseBuilder,CtorArgs...>(elemlib, elem, fact);
122  return ELI::LoadedLibraries::addLoader(elemlib, elem, loader);
123 }
124 
125 template <class Base, class T>
127  static bool isLoaded() {
128  return loaded;
129  }
130 
131  static const bool loaded;
132 };
133 
134 template <class Base, class T> const bool InstantiateBuilder<Base,T>::loaded
135  = Base::Ctor::template add<T>();
136 
137 template <class Base, class T, class Enable=void>
138 struct Allocator
139 {
140  template <class... Args>
141  T* operator()(Args&&... args){
142  return new T(std::forward<Args>(args)...);
143  }
144 };
145 
146 template <class Base, class T>
148 {
149  template <class... Args>
150  Base* operator()(Args&&... ctorArgs) {
151  if (!cached_){
152  cached_ = new T(std::forward<Args>(ctorArgs)...);
153  }
154  return cached_;
155  }
156 
157  static Base* cached_;
158 };
159 template <class Base, class T>
160  Base* CachedAllocator<Base,T>::cached_ = nullptr;
161 
162 template <class T, class Base, class... Args>
163 struct DerivedBuilder : public Builder<Base,Args...>
164 {
165  Base* create(Args... ctorArgs) override {
166  return Allocator<Base,T>()(std::forward<Args>(ctorArgs)...);
167  }
168 };
169 
170 
171 template <class T, class U>
172 struct is_tuple_constructible : public std::false_type {};
173 
174 template <class T, class... Args>
175 struct is_tuple_constructible<T, std::tuple<Args...>> :
176  public std::is_constructible<T, Args...>
177 {
178 };
179 
181  template <class T, class... Args>
182  static BuilderLibrary<T,Args...>* getLibrary(const std::string& name){
184  }
185 };
186 
187 template <class Base, class CtorTuple>
188 struct ElementsBuilder {};
189 
190 template <class Base, class... Args>
191 struct ElementsBuilder<Base, std::tuple<Args...>>
192 {
193  static BuilderLibrary<Base,Args...>* getLibrary(const std::string& name){
195  }
196 
197  template <class T> static Builder<Base,Args...>* makeBuilder(){
198  return new DerivedBuilder<T,Base,Args...>();
199  }
200 
201 };
202 
203 template <class NewCtor, class OldCtor>
205 {
206  template <class T> static bool add(){
207  //if abstract, force an allocation to generate meaningful errors
208  return NewCtor::template add<T>() && OldCtor::template add<T>();
209  }
210 
211  template <class __NewCtor>
213 
214  template <class NewBase>
215  using ChangeBase = typename NewCtor::template ChangeBase<NewBase>;
216 };
217 
218 template <class Base, class... Args>
220 {
221  template <class T> static bool add(){
222  //if abstract, force an allocation to generate meaningful errors
223  auto* fact = new DerivedBuilder<T,Base,Args...>;
224  return Base::addBuilder(T::ELI_getLibrary(),T::ELI_getName(),fact);
225  }
226 
227  template <class NewBase>
228  using ChangeBase = SingleCtor<NewBase, Args...>;
229 
230  template <class NewCtor>
231  using ExtendCtor = ExtendedCtor<NewCtor, SingleCtor<Base,Args...>>;
232 };
233 
234 
235 template <class Base, class Ctor, class... Ctors>
236 struct CtorList : public CtorList<Base,Ctors...>
237 {
238  template <class T, int NumValid=0, class U=T>
239  static typename std::enable_if<std::is_abstract<U>::value || is_tuple_constructible<U,Ctor>::value, bool>::type
240  add(){
241  //if abstract, force an allocation to generate meaningful errors
242  auto* fact = ElementsBuilder<Base,Ctor>::template makeBuilder<U>();
243  Base::addBuilder(T::ELI_getLibrary(),T::ELI_getName(),fact);
244  return CtorList<Base,Ctors...>::template add<T,NumValid+1>();
245  }
246 
247  template <class T, int NumValid=0, class U=T>
248  static typename std::enable_if<!std::is_abstract<U>::value && !is_tuple_constructible<U,Ctor>::value, bool>::type
249  add(){
250  return CtorList<Base,Ctors...>::template add<T,NumValid>();
251  }
252 
253  template <class NewBase>
254  using ChangeBase = CtorList<NewBase, Ctor, Ctors...>;
255 
256 };
257 
258 template <int NumValid>
260  static constexpr bool atLeastOneValidCtor = true;
261 };
262 
263 template <> class NoValidConstructorsForDerivedType<0> {};
264 
265 template <class Base> struct CtorList<Base,void>
266 {
267  template <class T,int numValidCtors>
268  static bool add(){
270  }
271 };
272 
273 }
274 }
275 
276 #define ELI_CTOR(...) std::tuple<__VA_ARGS__>
277 #define ELI_DEFAULT_CTOR() std::tuple<>
278 
279 #define SST_ELI_CTORS_COMMON(...) \
280  using Ctor = ::SST::ELI::CtorList<__LocalEliBase,__VA_ARGS__,void>; \
281  template <class __TT, class... __CtorArgs> \
282  using DerivedBuilder = ::SST::ELI::DerivedBuilder<__LocalEliBase,__TT,__CtorArgs...>; \
283  template <class... __InArgs> static SST::ELI::BuilderLibrary<__LocalEliBase,__InArgs...>* \
284  getBuilderLibraryTemplate(const std::string& name){ \
285  return ::SST::ELI::BuilderDatabase::getLibrary<__LocalEliBase,__InArgs...>(name); \
286  } \
287  template <class __TT> static bool addDerivedBuilder(const std::string& lib, const std::string& elem){ \
288  return Ctor::template add<0,__TT>(lib,elem); \
289  } \
290 
291 #define SST_ELI_DECLARE_CTORS(...) \
292  SST_ELI_CTORS_COMMON(ELI_FORWARD_AS_ONE(__VA_ARGS__)) \
293  template <class... Args> static bool addBuilder(const std::string& elemlib, const std::string& elem, \
294  SST::ELI::Builder<__LocalEliBase,Args...>* builder){ \
295  return getBuilderLibraryTemplate<Args...>(elemlib)->addBuilder(elem, builder); \
296  }
297 
298 #define SST_ELI_DECLARE_CTORS_EXTERN(...) \
299  SST_ELI_CTORS_COMMON(ELI_FORWARD_AS_ONE(__VA_ARGS__))
300 
301 //VA_ARGS here
302 // 0) Base name
303 // 1) List of ctor args
304 #define SST_ELI_BUILDER_TYPEDEFS(...) \
305  using BaseBuilder = ::SST::ELI::Builder<__VA_ARGS__>; \
306  using BuilderLibrary = ::SST::ELI::BuilderLibrary<__VA_ARGS__>; \
307  using BuilderLibraryDatabase = ::SST::ELI::BuilderLibraryDatabase<__VA_ARGS__>; \
308  template <class __TT> using DerivedBuilder = ::SST::ELI::DerivedBuilder<__TT,__VA_ARGS__>;
309 
310 #define SST_ELI_BUILDER_FXNS() \
311  static BuilderLibrary* getBuilderLibrary(const std::string& name){ \
312  return BuilderLibraryDatabase::getLibrary(name); \
313  } \
314  static bool addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder){ \
315  return getBuilderLibrary(elemlib)->addBuilder(elem,builder); \
316  }
317 
318 //I can make some extra using typedefs because I have only a single ctor
319 #define SST_ELI_DECLARE_CTOR(...) \
320  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
321  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase,__VA_ARGS__) \
322  SST_ELI_BUILDER_FXNS()
323 
324 #define SST_ELI_BUILDER_FXNS_EXTERN() \
325  static BuilderLibrary* getBuilderLibrary(const std::string& name); \
326  static bool addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder);
327 
328 #define SST_ELI_DECLARE_CTOR_EXTERN(...) \
329  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
330  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase,__VA_ARGS__); \
331  SST_ELI_BUILDER_FXNS_EXTERN()
332 
333 #define SST_ELI_DEFINE_CTOR_EXTERN(base) \
334  bool base::addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder){ \
335  return getBuilderLibrary(elemlib)->addBuilder(elem,builder); \
336  } \
337  base::BuilderLibrary* base::getBuilderLibrary(const std::string& elemlib){ \
338  return BuilderLibraryDatabase::getLibrary(elemlib); \
339  }
340 
341 //I can make some extra using typedefs because I have only a single ctor
342 #define SST_ELI_DECLARE_DEFAULT_CTOR() \
343  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase>; \
344  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase) \
345  SST_ELI_BUILDER_FXNS()
346 
347 #define SST_ELI_DECLARE_DEFAULT_CTOR_EXTERN() \
348  SST_ELI_DEFAULT_CTOR_COMMON() \
349  SST_ELI_BUILDER_FXNS_EXTERN()
350 
351 #define SST_ELI_EXTEND_CTOR() \
352  using Ctor = ::SST::ELI::ExtendedCtor<LocalCtor, __ParentEliBase::Ctor>;
353 
354 #define SST_ELI_SAME_BASE_CTOR() \
355  using LocalCtor = __ParentEliBase::Ctor::ChangeBase<__LocalEliBase>; \
356  SST_ELI_EXTEND_CTOR() \
357  using BaseBuilder = typename __ParentEliBase::BaseBuilder::template ChangeBase<__LocalEliBase>; \
358  using BuilderLibrary = __ParentEliBase::BuilderLibrary::ChangeBase<__LocalEliBase>; \
359  using BuilderLibraryDatabase = __ParentEliBase::BuilderLibraryDatabase::ChangeBase<__LocalEliBase>; \
360  SST_ELI_BUILDER_FXNS()
361 
362 #define SST_ELI_NEW_BASE_CTOR(...) \
363  using LocalCtor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
364  SST_ELI_EXTEND_CTOR() \
365  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase, __VA_ARGS__) \
366  SST_ELI_BUILDER_FXNS()
367 
368 #define SST_ELI_DEFAULT_BASE_CTOR() \
369  using LocalCtor = ::SST::ELI::SingleCtor<__LocalEliBase>; \
370  SST_ELI_EXTEND_CTOR() \
371  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase) \
372  SST_ELI_BUILDER_FXNS()
373 
374 
375 #endif
376 
Definition: elementbuilder.h:172
Definition: elementbuilder.h:188
Definition: elementbuilder.h:99
Definition: elementbuilder.h:236
Definition: elementbuilder.h:23
Definition: elementbuilder.h:163
Definition: elementbuilder.h:180
Definition: elementbuilder.h:259
Definition: elibase.h:107
Definition: elementbuilder.h:138
Definition: elementbuilder.h:126
Definition: elementbuilder.h:67
Definition: elementbuilder.h:219
Definition: elementbuilder.h:12
Definition: elementbuilder.h:204
Definition: elementbuilder.h:147
static bool addLoader(const std::string &lib, const std::string &name, LibraryLoader *loader)
Definition: elibase.cc:32