SST/macro
factory.h
Go to the documentation of this file.
1 /*
2  * This file is part of SST/macroscale:
3  * The macroscale architecture simulator from the SST suite.
4  * Copyright (c) 2009 Sandia Corporation.
5  * This software is distributed under the BSD License.
6  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7  * the U.S. Government retains certain rights in this software.
8  * For more information, see the LICENSE file in the top
9  * SST/macroscale directory.
10  */
11 
12 #ifndef SPROCKIT_COMMON_FACTORIES_FACTORY_H_INCLUDED
13 #define SPROCKIT_COMMON_FACTORIES_FACTORY_H_INCLUDED
14 
15 #include <cstdio>
16 #include <iostream>
17 #include <sprockit/errors.h>
18 #include <sprockit/statics.h>
21 #include <sprockit/spkt_config.h>
22 #include <map>
23 
24 namespace sprockit {
25 
26 class factory_type {
27 
28  public:
29  virtual void
30  init_factory_params(sim_parameters* params){
31  }
32 
33  virtual void
35  }
36 
37 };
38 
39 template <class T, typename... Args>
41 {
42  public:
43  virtual T*
44  build(const Args&... args) = 0;
45 
46 };
47 
48 template<class Child, class Factory>
50 {
51 };
52 
53 template<class T, typename... Args>
54 class Factory
55 {
56 
57  public:
58  typedef SpktBuilder<T,Args...> builder_t;
59  typedef T element_type;
60 
61  typedef std::map<std::string, builder_t*> builder_map;
62  static builder_map* builder_map_;
63  typedef std::map<std::string, std::list<std::string> > alias_map;
64  static alias_map* alias_map_;
65  static const char* name_;
66 
67  static void
68  register_alias(const std::string& oldname, const std::string& newname){
69  if (!builder_map_) {
70  builder_map_ = new builder_map;
71  }
72  if (!alias_map_){
73  alias_map_ = new alias_map;
74  }
75 
76  builder_t* base = (*builder_map_)[oldname];
77  if (!base){
78  (*alias_map_)[oldname].push_back(newname);
79  } else {
80  (*builder_map_)[newname] = base;
81  }
82  }
83 
84  static void
86  //do not iterate the builder map and delete entry
87  //each builder_t is a static objec that gets cleaned up automatically
88 
89  if (builder_map_) delete builder_map_;
90  if (alias_map_) delete alias_map_;
91 
92  builder_map_ = 0;
93  alias_map_ = 0;
94  }
95 
96  static void
97  register_name(const std::string& name, builder_t* descr) {
98  if (!builder_map_) {
99  builder_map_ = new builder_map;
100  }
101  if (!alias_map_){
102  alias_map_ = new alias_map;
103  }
104  add_to_map(name, descr, builder_map_, alias_map_);
105  }
106 
107  static void
108  add_to_map(const std::string& namestr, builder_t* desc,
109  std::map<std::string, builder_t*>* descr_map,
110  std::map<std::string, std::list<std::string> >* alias_map)
111  {
112  std::string space = "|";
113  std::deque<std::string> tok;
114  pst::BasicStringTokenizer::tokenize(namestr, tok, space);
115 
116  std::deque<std::string>::iterator it, end = tok.end();
117 
118  for (it = tok.begin(); it != end; it++) {
119  std::string temp = *it;
120 
121  temp = trim_str(temp);
122 
123  std::map<std::string, std::list<std::string> >::iterator it = alias_map->find(temp);
124  if (it != alias_map->end()){
125  std::list<std::string>& alias_list = it->second;
126  std::list<std::string>::iterator ait, end = alias_list.end();
127  for (ait=alias_list.begin(); ait != end; ++ait){
128  (*builder_map_)[*ait] = desc;
129  }
130  }
131 
132  (*builder_map_)[temp] = desc;
133  }
134  }
135 
136 
137  protected:
138  static T*
139  _get_value(const std::string& valname,
140  sprockit::sim_parameters* params,
141  const Args&... args) {
142  if (!builder_map_) {
144  "could not find name %s for factory %s. no classes are registered",
145  valname.c_str(),
146  name_);
147  }
148 
149  auto it = builder_map_->find(valname), end = builder_map_->end();
150 
151  if (it == end) {
152  std::cerr << "Valid factories are:" << std::endl;
153  for (it = builder_map_->begin(); it != end; ++it) {
154  std::cerr << it->first << std::endl;
155  }
156  spkt_throw_printf(value_error, "could not find name %s for factory %s",
157  valname.c_str(), name_);
158  }
159 
160  builder_t* descr = it->second;
161  if (!descr) {
163  "initialized name %s with null descr for factory %s",
164  valname.c_str(), name_);
165  }
166 
167  T* p = descr->build(args...);
168  p->init_factory_params(params);
169  p->finalize_init();
170  return p;
171  }
172 
173  public:
174  static T*
175  get_value(const std::string& valname,
176  sim_parameters* params,
177  const Args&... args) {
178  return _get_value(valname, params, args...);
179  }
180 
181  static T*
182  get_extra_param(const std::string& param_name,
183  sim_parameters* params,
184  const Args&... args) {
185  if (params->has_param(param_name)) {
186  return get_param(param_name,params);
187  }
188  else {
189  return 0;
190  }
191  }
192 
193  static T*
194  get_param(const std::string& param_name,
195  sim_parameters* params,
196  const Args&... args) {
197  return _get_value(params->get_param(param_name),
198  params, args...);
199  }
200 
201  static T*
202  get_optional_param(const std::string& param_name,
203  const std::string& defval,
204  sim_parameters* params,
205  const Args&... args) {
206  return _get_value(params->get_optional_param(param_name, defval),
207  params, args...);
208  }
209 
210 };
211 
212 template<class Child, typename Parent, typename... Args>
213 class SpktBuilderImpl<Child, Factory<Parent, Args...> > :
214  public SpktBuilder<Parent, Args...>
215 {
216  public:
217  SpktBuilderImpl(const char *name){
219  }
220 
221  Parent*
222  build(const Args&... args) {
223  return new Child(args...);
224  }
225 
226 };
227 
228 template <class T>
229 class factory
230 {
231  public:
232  virtual T* build(sim_parameters* params) = 0;
233 
234  virtual ~factory(){}
235 };
236 
237 template <class T, class Factory>
238 class template_factory : public factory<T>
239 {
240  public:
241  template_factory(const std::string& param_name)
242  : param_name_(param_name)
243  {
244  }
245 
246  T* build(sim_parameters* params){
247  typedef typename Factory::element_type F;
248  F* f = Factory::get_value(param_name_, params);
249  return f;
250  }
251 
252  private:
253  std::string param_name_;
254 };
255 
256 template <class T>
257 class factory2
258 {
259  public:
260  virtual ~factory2(){}
261 
262  virtual T* build(sim_parameters* params, sprockit::factory_type* ft) = 0;
263 };
264 
265 template <class T, class Factory>
266 class template_factory2 : public factory2<T>
267 {
268  public:
269  template_factory2(const std::string& param_name)
270  : param_name_(param_name)
271  {
272  }
273 
274  T* build(sim_parameters* params, sprockit::factory_type* ft){
275  typedef typename Factory::element_type F;
276  F* f = Factory::get_value(param_name_, params, ft);
277  return f;
278  }
279 
280  private:
281  std::string param_name_;
282 };
283 
284 template <class Factory>
286  public:
289  }
290 };
291 
292 }
293 
294 #define FirstArgStr(X, ...) #X
295 #define FirstArgFactoryName(X, ...) X##_factory
296 
297 #define DeclareFactory(...) \
298  typedef ::sprockit::Factory<__VA_ARGS__> FirstArgFactoryName(__VA_ARGS__);
299 
300 #define ImplementFactory(type_name) \
301  template<> const char* type_name##_factory::name_ = #type_name; \
302  template<> std::map<std::string, type_name##_factory::builder_t*>* type_name##_factory::builder_map_ = 0; \
303  template<> std::map<std::string, std::list<std::string>>* type_name##_factory::alias_map_ = 0; \
304  namespace { static sprockit::CleanupFactory<type_name##_factory> cleaner; }
305 
306 
307 
308 #define SpktTemplateRegister(cls_str, parent_cls, child_cls, unique_name, ...) \
309  static ::sprockit::SpktBuilderImpl<child_cls, parent_cls##_factory> unique_name##_cd(cls_str)
310 
311 #define SpktRegister(cls_str, parent_cls, child_cls, ...) \
312  static ::sprockit::SpktBuilderImpl<child_cls,parent_cls##_factory> child_cls##_cd(cls_str)
313 
314 
315 #define DeclareFactory1InitParam(type_name, param1_name) \
316  DeclareFactory(type_name, param1_name);
317 
318 #define DeclareFactory2InitParams(type_name, param1_name, param2_name) \
319  DeclareFactory(type_name, param1_name, param2_name);
320 
321 #define DeclareFactory3InitParams(type_name, param1_name, param2_name, param3_name) \
322  DeclareFactory(type_name, param1_name, param2_name, param3_name);
323 
324 #endif
325 
template_factory2(const std::string &param_name)
Definition: factory.h:269
static void register_alias(const std::string &oldname, const std::string &newname)
Definition: factory.h:68
static T * get_value(const std::string &valname, sim_parameters *params, const Args &...args)
Definition: factory.h:175
const char * get_param(char *str)
static void add_to_map(const std::string &namestr, builder_t *desc, std::map< std::string, builder_t * > *descr_map, std::map< std::string, std::list< std::string > > *alias_map)
Definition: factory.h:108
static T * _get_value(const std::string &valname, sprockit::sim_parameters *params, const Args &...args)
Definition: factory.h:139
void tokenize(const typename std::basic_string< CharType, Traits, StrAlloc > &str, typename std::deque< typename std::basic_string< CharType, Traits, StrAlloc >, DqAlloc > &tok, const typename std::basic_string< CharType, Traits, StrAlloc > &space=" \t\n")
A utility function to tokenize a std::string.
std::string trim_str(const std::string &Src, const std::string &c=" \r\n")
std::map< std::string, std::list< std::string > > alias_map
Definition: factory.h:63
SpktBuilder< T, Args... > builder_t
Definition: factory.h:58
static T * get_extra_param(const std::string &param_name, sim_parameters *params, const Args &...args)
Definition: factory.h:182
static void register_name(const std::string &name, builder_t *descr)
Definition: factory.h:97
virtual ~factory2()
Definition: factory.h:260
static T * get_param(const std::string &param_name, sim_parameters *params, const Args &...args)
Definition: factory.h:194
virtual void finalize_init()
Definition: factory.h:34
An error indicating some format was not correct.
Definition: errors.h:131
static alias_map * alias_map_
Definition: factory.h:64
std::string param_name_
Definition: factory.h:253
virtual void init_factory_params(sim_parameters *params)
Definition: factory.h:30
template_factory(const std::string &param_name)
Definition: factory.h:241
#define spkt_throw_printf(exc, template_str,...)
Definition: errors.h:37
static void clean_up()
Definition: factory.h:85
std::map< std::string, builder_t * > builder_map
Definition: factory.h:61
static T * get_optional_param(const std::string &param_name, const std::string &defval, sim_parameters *params, const Args &...args)
Definition: factory.h:202
virtual ~factory()
Definition: factory.h:234
static const char * name_
Definition: factory.h:65
static builder_map * builder_map_
Definition: factory.h:62
T * build(sim_parameters *params)
Definition: factory.h:246
Error indicating some internal value was unexpected.
Definition: errors.h:83
T * build(sim_parameters *params, sprockit::factory_type *ft)
Definition: factory.h:274