SST  9.0.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... CtorArgs>
99 bool BuilderLibrary<Base,CtorArgs...>::addLoader(const std::string &elemlib, const std::string &elem, BaseBuilder *fact){
100  return ELI::LoadedLibraries::addLoader(elemlib, elem, [=]{
101  BuilderLibraryDatabase<Base,CtorArgs...>::getLibrary(elemlib)->readdBuilder(elem,fact);
102  });
103 }
104 
105 template <class Base, class T>
107  static bool isLoaded() {
108  return loaded;
109  }
110 
111  static const bool loaded;
112 };
113 
114 template <class Base, class T> const bool InstantiateBuilder<Base,T>::loaded
115  = Base::Ctor::template add<T>();
116 
117 template <class Base, class T, class Enable=void>
118 struct Allocator
119 {
120  template <class... Args>
121  T* operator()(Args&&... args){
122  return new T(std::forward<Args>(args)...);
123  }
124 };
125 
126 template <class Base, class T>
128 {
129  template <class... Args>
130  Base* operator()(Args&&... ctorArgs) {
131  if (!cached_){
132  cached_ = new T(std::forward<Args>(ctorArgs)...);
133  }
134  return cached_;
135  }
136 
137  static Base* cached_;
138 };
139 template <class Base, class T>
140  Base* CachedAllocator<Base,T>::cached_ = nullptr;
141 
142 template <class T, class Base, class... Args>
143 struct DerivedBuilder : public Builder<Base,Args...>
144 {
145  Base* create(Args... ctorArgs) override {
146  return Allocator<Base,T>()(std::forward<Args>(ctorArgs)...);
147  }
148 };
149 
150 
151 template <class T, class U>
152 struct is_tuple_constructible : public std::false_type {};
153 
154 template <class T, class... Args>
155 struct is_tuple_constructible<T, std::tuple<Args...>> :
156  public std::is_constructible<T, Args...>
157 {
158 };
159 
161  template <class T, class... Args>
162  static BuilderLibrary<T,Args...>* getLibrary(const std::string& name){
164  }
165 };
166 
167 template <class Base, class CtorTuple>
168 struct ElementsBuilder {};
169 
170 template <class Base, class... Args>
171 struct ElementsBuilder<Base, std::tuple<Args...>>
172 {
173  static BuilderLibrary<Base,Args...>* getLibrary(const std::string& name){
175  }
176 
177  template <class T> static Builder<Base,Args...>* makeBuilder(){
178  return new DerivedBuilder<T,Base,Args...>();
179  }
180 
181 };
182 
183 template <class NewCtor, class OldCtor>
185 {
186  template <class T> static bool add(){
187  //if abstract, force an allocation to generate meaningful errors
188  return NewCtor::template add<T>() && OldCtor::template add<T>();
189  }
190 
191  template <class __NewCtor>
193 
194  template <class NewBase>
195  using ChangeBase = typename NewCtor::template ChangeBase<NewBase>;
196 };
197 
198 template <class Base, class... Args>
200 {
201  template <class T> static bool add(){
202  //if abstract, force an allocation to generate meaningful errors
203  auto* fact = new DerivedBuilder<T,Base,Args...>;
204  return Base::addBuilder(T::ELI_getLibrary(),T::ELI_getName(),fact);
205  }
206 
207  template <class NewBase>
208  using ChangeBase = SingleCtor<NewBase, Args...>;
209 
210  template <class NewCtor>
211  using ExtendCtor = ExtendedCtor<NewCtor, SingleCtor<Base,Args...>>;
212 };
213 
214 
215 template <class Base, class Ctor, class... Ctors>
216 struct CtorList : public CtorList<Base,Ctors...>
217 {
218  template <class T, int NumValid=0, class U=T>
219  static typename std::enable_if<std::is_abstract<U>::value || is_tuple_constructible<U,Ctor>::value, bool>::type
220  add(){
221  //if abstract, force an allocation to generate meaningful errors
222  auto* fact = ElementsBuilder<Base,Ctor>::template makeBuilder<U>();
223  Base::addBuilder(T::ELI_getLibrary(),T::ELI_getName(),fact);
224  return CtorList<Base,Ctors...>::template add<T,NumValid+1>();
225  }
226 
227  template <class T, int NumValid=0, class U=T>
228  static typename std::enable_if<!std::is_abstract<U>::value && !is_tuple_constructible<U,Ctor>::value, bool>::type
229  add(){
230  return CtorList<Base,Ctors...>::template add<T,NumValid>();
231  }
232 
233  template <class NewBase>
234  using ChangeBase = CtorList<NewBase, Ctor, Ctors...>;
235 
236 };
237 
238 template <int NumValid>
240  static constexpr bool atLeastOneValidCtor = true;
241 };
242 
243 template <> class NoValidConstructorsForDerivedType<0> {};
244 
245 template <class Base> struct CtorList<Base,void>
246 {
247  template <class T,int numValidCtors>
248  static bool add(){
250  }
251 };
252 
253 }
254 }
255 
256 #define ELI_CTOR(...) std::tuple<__VA_ARGS__>
257 #define ELI_DEFAULT_CTOR() std::tuple<>
258 
259 #define SST_ELI_CTORS_COMMON(...) \
260  using Ctor = ::SST::ELI::CtorList<__LocalEliBase,__VA_ARGS__,void>; \
261  template <class __TT, class... __CtorArgs> \
262  using DerivedBuilder = ::SST::ELI::DerivedBuilder<__LocalEliBase,__TT,__CtorArgs...>; \
263  template <class... __InArgs> static SST::ELI::BuilderLibrary<__LocalEliBase,__InArgs...>* \
264  getBuilderLibraryTemplate(const std::string& name){ \
265  return ::SST::ELI::BuilderDatabase::getLibrary<__LocalEliBase,__InArgs...>(name); \
266  } \
267  template <class __TT> static bool addDerivedBuilder(const std::string& lib, const std::string& elem){ \
268  return Ctor::template add<0,__TT>(lib,elem); \
269  } \
270 
271 #define SST_ELI_DECLARE_CTORS(...) \
272  SST_ELI_CTORS_COMMON(ELI_FORWARD_AS_ONE(__VA_ARGS__)) \
273  template <class... Args> static bool addBuilder(const std::string& elemlib, const std::string& elem, \
274  SST::ELI::Builder<__LocalEliBase,Args...>* builder){ \
275  return getBuilderLibraryTemplate<Args...>(elemlib)->addBuilder(elem, builder); \
276  }
277 
278 #define SST_ELI_DECLARE_CTORS_EXTERN(...) \
279  SST_ELI_CTORS_COMMON(ELI_FORWARD_AS_ONE(__VA_ARGS__))
280 
281 //VA_ARGS here
282 // 0) Base name
283 // 1) List of ctor args
284 #define SST_ELI_BUILDER_TYPEDEFS(...) \
285  using BaseBuilder = ::SST::ELI::Builder<__VA_ARGS__>; \
286  using BuilderLibrary = ::SST::ELI::BuilderLibrary<__VA_ARGS__>; \
287  using BuilderLibraryDatabase = ::SST::ELI::BuilderLibraryDatabase<__VA_ARGS__>; \
288  template <class __TT> using DerivedBuilder = ::SST::ELI::DerivedBuilder<__TT,__VA_ARGS__>;
289 
290 #define SST_ELI_BUILDER_FXNS() \
291  static BuilderLibrary* getBuilderLibrary(const std::string& name){ \
292  return BuilderLibraryDatabase::getLibrary(name); \
293  } \
294  static bool addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder){ \
295  return getBuilderLibrary(elemlib)->addBuilder(elem,builder); \
296  }
297 
298 //I can make some extra using typedefs because I have only a single ctor
299 #define SST_ELI_DECLARE_CTOR(...) \
300  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
301  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase,__VA_ARGS__) \
302  SST_ELI_BUILDER_FXNS()
303 
304 #define SST_ELI_BUILDER_FXNS_EXTERN() \
305  static BuilderLibrary* getBuilderLibrary(const std::string& name); \
306  static bool addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder);
307 
308 #define SST_ELI_DECLARE_CTOR_EXTERN(...) \
309  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
310  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase,__VA_ARGS__); \
311  SST_ELI_BUILDER_FXNS_EXTERN()
312 
313 #define SST_ELI_DEFINE_CTOR_EXTERN(base) \
314  bool base::addBuilder(const std::string& elemlib, const std::string& elem, BaseBuilder* builder){ \
315  return getBuilderLibrary(elemlib)->addBuilder(elem,builder); \
316  } \
317  base::BuilderLibrary* base::getBuilderLibrary(const std::string& elemlib){ \
318  return BuilderLibraryDatabase::getLibrary(elemlib); \
319  }
320 
321 //I can make some extra using typedefs because I have only a single ctor
322 #define SST_ELI_DECLARE_DEFAULT_CTOR() \
323  using Ctor = ::SST::ELI::SingleCtor<__LocalEliBase>; \
324  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase) \
325  SST_ELI_BUILDER_FXNS()
326 
327 #define SST_ELI_DECLARE_DEFAULT_CTOR_EXTERN() \
328  SST_ELI_DEFAULT_CTOR_COMMON() \
329  SST_ELI_BUILDER_FXNS_EXTERN()
330 
331 #define SST_ELI_EXTEND_CTOR() \
332  using Ctor = ::SST::ELI::ExtendedCtor<LocalCtor, __ParentEliBase::Ctor>;
333 
334 #define SST_ELI_SAME_BASE_CTOR() \
335  using LocalCtor = __ParentEliBase::Ctor::ChangeBase<__LocalEliBase>; \
336  SST_ELI_EXTEND_CTOR() \
337  using BaseBuilder = typename __ParentEliBase::BaseBuilder::template ChangeBase<__LocalEliBase>; \
338  using BuilderLibrary = __ParentEliBase::BuilderLibrary::ChangeBase<__LocalEliBase>; \
339  using BuilderLibraryDatabase = __ParentEliBase::BuilderLibraryDatabase::ChangeBase<__LocalEliBase>; \
340  SST_ELI_BUILDER_FXNS()
341 
342 #define SST_ELI_NEW_BASE_CTOR(...) \
343  using LocalCtor = ::SST::ELI::SingleCtor<__LocalEliBase,__VA_ARGS__>; \
344  SST_ELI_EXTEND_CTOR() \
345  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase, __VA_ARGS__) \
346  SST_ELI_BUILDER_FXNS()
347 
348 #define SST_ELI_DEFAULT_BASE_CTOR() \
349  using LocalCtor = ::SST::ELI::SingleCtor<__LocalEliBase>; \
350  SST_ELI_EXTEND_CTOR() \
351  SST_ELI_BUILDER_TYPEDEFS(__LocalEliBase) \
352  SST_ELI_BUILDER_FXNS()
353 
354 
355 #endif
356 
static bool addLoader(const std::string &lib, const std::string &name, std::function< void()> &&loader)
Definition: elibase.cc:32
Definition: elementbuilder.h:152
Definition: elementbuilder.h:168
Definition: elementbuilder.h:216
Definition: elementbuilder.h:23
Definition: elementbuilder.h:143
Definition: elementbuilder.h:160
Definition: elementbuilder.h:239
Definition: elementbuilder.h:118
Definition: elementbuilder.h:106
Definition: elementbuilder.h:67
Definition: elementbuilder.h:199
Definition: elementbuilder.h:12
Definition: elementbuilder.h:184
Definition: elementbuilder.h:127