Scarab  v2.2.1
Project 8 C++ Utility Library
factory.hh
Go to the documentation of this file.
1 /*
2  * mt_factory.hh
3  *
4  * created on: Jul 31, 2012
5  * Author: nsoblath
6  */
7 
8 #ifndef SCARAB_FACTORY_HH_
9 #define SCARAB_FACTORY_HH_
10 
11 #include "singleton.hh"
12 
13 #include "logger.hh"
14 
15 #include <map>
16 #include <string>
17 #include <utility>
18 
19 namespace scarab
20 {
21  LOGGER( slog_fact, "factory" );
22 
23  //********************
24  // Class definitions
25  //********************
26 
27  template< class XBaseType, typename ... XArgs >
28  class factory;
29 
30  // base_registrar
31 
32  template< class XBaseType, typename ... XArgs >
34  {
35  public:
37  virtual ~base_registrar() {}
38 
39  public:
40  friend class factory< XBaseType, XArgs... >;
41 
42  protected:
43  virtual XBaseType* create( XArgs ... args ) const = 0;
44 
45  };
46 
47  // registrar
48 
49  template< class XBaseType, class XDerivedType, typename ... XArgs >
50  class registrar : public base_registrar< XBaseType, XArgs... >
51  {
52  public:
53  registrar( const std::string& a_class_name );
54  virtual ~registrar();
55 
56  protected:
57  void register_class( const std::string& a_class_name ) const;
58 
59  XBaseType* create( XArgs ... args ) const;
60 
61  std::string f_class_name;
62  };
63 
64  // factory
65 
66  template< class XBaseType, typename ... XArgs >
67  class factory : public singleton< factory< XBaseType, XArgs... > >
68  {
69  public:
70  typedef std::map< std::string, const base_registrar< XBaseType, XArgs... >* > FactoryMap;
71  typedef typename FactoryMap::value_type FactoryEntry;
72  typedef typename FactoryMap::iterator FactoryIt;
73  typedef typename FactoryMap::const_iterator FactoryCIt;
74 
75  public:
76  XBaseType* create( const std::string& a_class_name, XArgs ... args );
77  XBaseType* create( const FactoryCIt& iter, XArgs ... args );
78 
79  void register_class( const std::string& a_class_name, const base_registrar< XBaseType, XArgs... >* base_registrar );
80  bool has_class( const std::string& a_class_name ) const;
81  void remove_class( const std::string& a_class_name );
82 
83  FactoryCIt begin() const;
84  FactoryCIt end() const;
85 
86  protected:
88  std::mutex f_factory_mutex;
89 
90  protected:
92  factory();
93  ~factory();
94  };
95 
96 
97  //*****************************************
98  // Partial specialization for empty XArgs
99  //*****************************************
100 
101  template< class XBaseType >
102  class base_registrar< XBaseType, void >
103  {
104  public:
106  virtual ~base_registrar() {}
107 
108  public:
109  friend class factory< XBaseType >;
110 
111  protected:
112  virtual XBaseType* create() const = 0;
113 
114  };
115 
116  template< class XBaseType, class XDerivedType >
117  class registrar< XBaseType, XDerivedType, void > : public base_registrar< XBaseType >
118  {
119  public:
120  registrar( const std::string& a_class_name );
121  virtual ~registrar();
122 
123  protected:
124  void register_class( const std::string& a_class_name ) const;
125 
126  XBaseType* create() const;
127 
128  std::string f_class_name;
129  };
130 
131 
132  template< class XBaseType >
133  class factory< XBaseType, void > : public singleton< factory< XBaseType > >
134  {
135  public:
136  typedef std::map< std::string, const base_registrar< XBaseType >* > FactoryMap;
137  typedef typename FactoryMap::value_type FactoryEntry;
138  typedef typename FactoryMap::iterator FactoryIt;
139  typedef typename FactoryMap::const_iterator FactoryCIt;
140 
141  public:
142  XBaseType* create( const std::string& a_class_name );
143  XBaseType* create( const FactoryCIt& iter );
144 
145  void register_class( const std::string& a_class_name, const base_registrar< XBaseType >* base_registrar );
146  bool has_class( const std::string& a_class_name ) const;
147  void remove_class( const std::string& a_class_name );
148 
149  FactoryCIt begin() const;
150  FactoryCIt end() const;
151 
152  protected:
153  FactoryMap* fMap;
154  std::mutex f_factory_mutex;
155 
156  protected:
157  friend class singleton< factory >;
158  friend class destroyer< factory >;
159  factory();
160  ~factory();
161  };
162 
163 
164  //******************
165  // Implementations
166  //******************
167 
168  // factory
169 
170  template< class XBaseType, typename ... XArgs >
171  XBaseType* factory< XBaseType, XArgs... >::create( const FactoryCIt& iter, XArgs ... args )
172  {
173  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
174  return iter->second->create( args... );
175  }
176 
177  template< class XBaseType, typename ... XArgs >
178  XBaseType* factory< XBaseType, XArgs... >::create( const std::string& a_class_name, XArgs ... args )
179  {
180  //std::cout << "this factory (" << this << ") has " << fMap->size() << " entries" << std::endl;
181  //for( FactoryCIt iter = fMap->begin(); iter != fMap->end(); ++iter )
182  //{
183  // std::cout << "this factory has: " << iter->first << " at " << iter->second << std::endl;
184  //}
185  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
186  FactoryCIt it = fMap->find( a_class_name );
187  if( it == fMap->end() )
188  {
189  LERROR( slog_fact, "Did not find factory for <" << a_class_name << ">." );
190  return NULL;
191  }
192 
193  return it->second->create( args... );
194  }
195 
196  template< class XBaseType, typename ... XArgs >
197  void factory< XBaseType, XArgs... >::register_class( const std::string& a_class_name, const base_registrar< XBaseType, XArgs... >* a_registrar )
198  {
199  // A local (static) logger is created inside this function to avoid static initialization order problems
200  LOGGER( slog_factory_reg, "factory-register");
201 
202  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
203  FactoryCIt it = fMap->find(a_class_name);
204  if (it != fMap->end())
205  {
206  LERROR( slog_factory_reg, "Already have factory registered for <" << a_class_name << ">." );
207  return;
208  }
209  fMap->insert(std::pair< std::string, const base_registrar< XBaseType, XArgs... >* >(a_class_name, a_registrar));
210  LDEBUG( slog_factory_reg, "Registered a factory for class " << a_class_name << " at " << (*fMap)[ a_class_name ] << ", factory #" << fMap->size()-1 << " for " << this );
211  }
212 
213  template< class XBaseType, typename ... XArgs >
214  bool factory< XBaseType, XArgs... >::has_class(const std::string& a_class_name ) const
215  {
216  return fMap->find( a_class_name ) != fMap->end();
217  }
218 
219  template< class XBaseType, typename ... XArgs >
220  void factory< XBaseType, XArgs... >::remove_class(const std::string& a_class_name )
221  {
222  LDEBUG( slog_fact, "Removing factory for class " << a_class_name << " from " << this );
223  FactoryIt iter = fMap->find( a_class_name );
224  if( iter != fMap->end() ) fMap->erase( iter );
225  return;
226  }
227 
228  template< class XBaseType, typename ... XArgs >
230  fMap(new FactoryMap()),
231  f_factory_mutex()
232  {}
233 
234  template< class XBaseType, typename ... XArgs >
236  {
237  delete fMap;
238  }
239 
240  template< class XBaseType, typename ... XArgs >
241  typename factory< XBaseType, XArgs... >::FactoryCIt factory< XBaseType, XArgs... >::begin() const
242  {
243  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
244  return fMap->begin();
245  }
246 
247  template< class XBaseType, typename ... XArgs >
248  typename factory< XBaseType, XArgs... >::FactoryCIt factory< XBaseType, XArgs... >::end() const
249  {
250  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
251  return fMap->end();
252  }
253 
254  // registrar
255 
256  template< class XBaseType, class XDerivedType, typename ... XArgs >
258  base_registrar< XBaseType, XArgs... >(),
259  f_class_name( a_class_name )
260  {
261  register_class( a_class_name );
262  }
263 
264  template< class XBaseType, class XDerivedType, typename ... XArgs >
266  {
268  }
269 
270  template< class XBaseType, class XDerivedType, typename ... XArgs >
271  void registrar< XBaseType, XDerivedType, XArgs... >::register_class( const std::string& a_class_name ) const
272  {
274  return;
275  }
276 
277  template< class XBaseType, class XDerivedType, typename ... XArgs >
279  {
280  return dynamic_cast< XBaseType* >( new XDerivedType( args... ) );
281  }
282 
283 
284  //*******************************************
285  // Implementations (partial specialization)
286  //*******************************************
287 
288  // factory
289 
290  template< class XBaseType >
292  {
293  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
294  return iter->second->create();
295  }
296 
297  template< class XBaseType >
298  XBaseType* factory< XBaseType, void >::create( const std::string& a_class_name )
299  {
300  //std::cout << "this factory (" << this << ") has " << fMap->size() << " entries" << std::endl;
301  //for( FactoryCIt iter = fMap->begin(); iter != fMap->end(); ++iter )
302  //{
303  // std::cout << "this factory has: " << iter->first << " at " << iter->second << std::endl;
304  //}
305  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
306  FactoryCIt it = fMap->find( a_class_name );
307  if( it == fMap->end() )
308  {
309  LERROR( slog_fact, "Did not find factory for <" << a_class_name << ">." );
310  return NULL;
311  }
312 
313  return it->second->create();
314  }
315 
316  template< class XBaseType >
317  void factory< XBaseType, void >::register_class( const std::string& a_class_name, const base_registrar< XBaseType >* a_registrar )
318  {
319  // A local (static) logger is created inside this function to avoid static initialization order problems
320  LOGGER( slog_factory_reg, "factory-register");
321 
322  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
323  FactoryCIt it = fMap->find(a_class_name);
324  if (it != fMap->end())
325  {
326  LERROR( slog_factory_reg, "Already have factory registered for <" << a_class_name << ">." );
327  return;
328  }
329  fMap->insert(std::pair< std::string, const base_registrar< XBaseType >* >(a_class_name, a_registrar));
330  LDEBUG( slog_factory_reg, "Registered a factory for class " << a_class_name << ", factory #" << fMap->size()-1 << " for " << this );
331  }
332 
333  template< class XBaseType >
334  bool factory< XBaseType, void >::has_class(const std::string& a_class_name ) const
335  {
336  return fMap->find( a_class_name ) != fMap->end();
337  }
338 
339  template< class XBaseType >
340  void factory< XBaseType, void >::remove_class(const std::string& a_class_name )
341  {
342  LDEBUG( slog_fact, "Removing factory for class " << a_class_name << " from " << this );
343  FactoryIt iter = fMap->find( a_class_name );
344  if( iter != fMap->end() ) fMap->erase( iter );
345  return;
346  }
347 
348  template< class XBaseType >
350  fMap(new FactoryMap()),
351  f_factory_mutex()
352  {}
353 
354  template< class XBaseType >
356  {
357  delete fMap;
358  }
359 
360  template< class XBaseType >
362  {
363  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
364  return fMap->begin();
365  }
366 
367  template< class XBaseType >
369  {
370  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
371  return fMap->end();
372  }
373 
374  // registrar
375 
376  template< class XBaseType, class XDerivedType >
377  registrar< XBaseType, XDerivedType, void >::registrar( const std::string& a_class_name ) :
378  base_registrar< XBaseType >(),
379  f_class_name( a_class_name )
380  {
381  register_class( a_class_name );
382  }
383 
384  template< class XBaseType, class XDerivedType >
386  {
388  }
389 
390  template< class XBaseType, class XDerivedType >
391  void registrar< XBaseType, XDerivedType, void >::register_class( const std::string& a_class_name ) const
392  {
393  factory< XBaseType >::get_instance()->register_class( a_class_name, this );
394  return;
395  }
396 
397  template< class XBaseType, class XDerivedType >
399  {
400  return dynamic_cast< XBaseType* >( new XDerivedType() );
401  }
402 
403 } /* namespace scarab */
404 #endif /* SCARAB_FACTORY_HH_ */
virtual ~base_registrar()
Definition: factory.hh:37
FactoryCIt begin() const
Definition: factory.hh:241
FactoryCIt end() const
Definition: factory.hh:248
FactoryMap::const_iterator FactoryCIt
Definition: factory.hh:73
virtual ~registrar()
Definition: factory.hh:265
static factory< XBaseType, XArgs... > * get_instance()
#define LERROR(...)
Definition: logger.hh:365
void register_class(const std::string &a_class_name, const base_registrar< XBaseType, XArgs... > *base_registrar)
Definition: factory.hh:197
FactoryMap::value_type FactoryEntry
Definition: factory.hh:137
registrar(const std::string &a_class_name)
Definition: factory.hh:257
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
FactoryMap::iterator FactoryIt
Definition: factory.hh:138
#define LDEBUG(...)
Definition: logger.hh:360
XBaseType * create(XArgs...args) const
Definition: factory.hh:278
std::map< std::string, const base_registrar< XBaseType > * > FactoryMap
Definition: factory.hh:136
FactoryMap::iterator FactoryIt
Definition: factory.hh:72
void register_class(const std::string &a_class_name) const
Definition: factory.hh:271
virtual XBaseType * create(XArgs...args) const =0
bool has_class(const std::string &a_class_name) const
Definition: factory.hh:214
std::mutex f_factory_mutex
Definition: factory.hh:88
std::map< std::string, const base_registrar< XBaseType, XArgs... > * > FactoryMap
Definition: factory.hh:70
XBaseType * create(const std::string &a_class_name, XArgs...args)
Definition: factory.hh:178
FactoryMap::const_iterator FactoryCIt
Definition: factory.hh:139
FactoryMap * fMap
Definition: factory.hh:87
void remove_class(const std::string &a_class_name)
Definition: factory.hh:220
#define allow_singleton_access(class_name)
Definition: singleton.hh:13
FactoryMap::value_type FactoryEntry
Definition: factory.hh:71
std::string f_class_name
Definition: factory.hh:61
LOGGER(mtlog,"authentication")