Scarab  v3.2.4
Project 8 C++ Utility Library
indexed_factory.hh
Go to the documentation of this file.
1 /*
2  * indexed_factory.hh
3  *
4  * created on: Oct 4, 2019
5  * Author: N.S. Oblath
6  *
7  * This factory has the same functionality as is found in factory.hh plus the option of choosing the index type.
8  *
9  * Note on registrar lifespan: when a registrar is deleted, it un-registers itself from the factory.
10  * This is because the registrar itself is used to create objects, and the act of registering
11  * stores a pointer in the factory. The factory does _not_ assume ownership of the registrar.
12  * Therefore the registrar needs to exist for as long as it might be needed.
13  */
14 
15 #ifndef SCARAB_INDEXED_FACTORY_HH_
16 #define SCARAB_INDEXED_FACTORY_HH_
17 
18 #include "singleton.hh"
19 
20 #include "error.hh"
21 #include "logger.hh"
22 
23 #include <map>
24 #include <string>
25 #include <utility>
26 
27 namespace scarab
28 {
29  LOGGER( slog_ind_fact, "indexed_factory" );
30 
31  //********************
32  // Class definitions
33  //********************
34 
35  template< class XIndexType, class XBaseType, typename ... XArgs >
37 
38  // base_registrar
39 
40  template< class XBaseType, typename ... XArgs >
42  {
43  public:
45  virtual ~base_registrar() {}
46 
47  virtual XBaseType* create( XArgs ... args ) const = 0;
48 
49  };
50 
51  // registrar
52 
53  template< class XIndexType, class XBaseType, class XDerivedType, typename ... XArgs >
54  class indexed_registrar : public base_registrar< XBaseType, XArgs... >
55  {
56  public:
57  indexed_registrar( const XIndexType& a_index );
58  virtual ~indexed_registrar();
59 
60  void register_class() const;
61 
62  XBaseType* create( XArgs ... args ) const;
63 
64  protected:
65  XIndexType f_index;
66  };
67 
68  // indexed_factory
69 
70  template< class XIndexType, class XBaseType, typename ... XArgs >
71  class indexed_factory : public singleton< indexed_factory< XIndexType, XBaseType, XArgs... > >
72  {
73  public:
74  typedef std::map< XIndexType, const base_registrar< XBaseType, XArgs... >* > FactoryMap;
75  typedef typename FactoryMap::value_type FactoryEntry;
76  typedef typename FactoryMap::iterator FactoryIt;
77  typedef typename FactoryMap::const_iterator FactoryCIt;
78 
79  public:
80  XBaseType* create( const XIndexType& a_index, XArgs ... args );
81  XBaseType* create( const FactoryCIt& iter, XArgs ... args );
82 
83  void register_class( const XIndexType& a_index, const base_registrar< XBaseType, XArgs... >* base_registrar );
84  bool has_class( const XIndexType& a_index ) const;
85  void remove_class( const XIndexType& a_index );
86 
87  FactoryCIt begin() const;
88  FactoryCIt end() const;
89 
90  protected:
92  mutable std::mutex f_factory_mutex;
93 
94  protected:
97  ~indexed_factory();
98  };
99 
100 
101  //*****************************************
102  // Partial specialization for empty XArgs
103  //*****************************************
104 
105  template< class XBaseType >
106  class base_registrar< XBaseType, void >
107  {
108  public:
110  virtual ~base_registrar() {}
111 
112  virtual XBaseType* create() const = 0;
113 
114  };
115 
116  template< class XIndexType, class XBaseType, class XDerivedType >
117  class indexed_registrar< XIndexType, XBaseType, XDerivedType, void > : public base_registrar< XBaseType >
118  {
119  public:
120  indexed_registrar( const XIndexType& a_index );
121  virtual ~indexed_registrar();
122 
123  void register_class() const;
124 
125  XBaseType* create() const;
126 
127  protected:
128  XIndexType f_index;
129  };
130 
131 
132  template< class XIndexType, class XBaseType >
133  class indexed_factory< XIndexType, XBaseType, void > : public singleton< indexed_factory< XIndexType, XBaseType > >
134  {
135  public:
136  typedef std::map< XIndexType, 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 XIndexType& a_index );
143  XBaseType* create( const FactoryCIt& iter );
144 
145  void register_class( const XIndexType& a_index, const base_registrar< XBaseType >* base_registrar );
146  bool has_class( const XIndexType& a_index ) const;
147  void remove_class( const XIndexType& a_index );
148 
149  FactoryCIt begin() const;
150  FactoryCIt end() const;
151 
152  protected:
153  FactoryMap* fMap;
154  std::mutex f_factory_mutex;
155 
156  protected:
158  indexed_factory();
159  ~indexed_factory();
160  };
161 
162 
163  //******************
164  // Implementations
165  //******************
166 
167  // indexed_factory
168 
169  template< class XIndexType, class XBaseType, typename ... XArgs >
171  {
172  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
173  return iter->second->create( args... );
174  }
175 
176  template< class XIndexType, class XBaseType, typename ... XArgs >
177  XBaseType* indexed_factory< XIndexType, XBaseType, XArgs... >::create( const XIndexType& a_index, XArgs ... args )
178  {
179  //std::cout << "this factory (" << this << ") has " << fMap->size() << " entries" << std::endl;
180  //for( FactoryCIt iter = fMap->begin(); iter != fMap->end(); ++iter )
181  //{
182  // std::cout << "this factory has: " << iter->first << " at " << iter->second << std::endl;
183  //}
184  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
185  FactoryCIt it = fMap->find( a_index );
186  if( it == fMap->end() )
187  {
188  LERROR( slog_ind_fact, "Did not find indexed_factory for <" << a_index << ">." );
189  return nullptr;
190  }
191 
192  return it->second->create( args... );
193  }
194 
195  template< class XIndexType, class XBaseType, typename ... XArgs >
197  {
198  // A local (static) logger is created inside this function to avoid static initialization order problems
199  LOGGER( slog_ind_factory_reg, "indexed_factory-register");
200 
201  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
202  FactoryCIt it = fMap->find(a_index);
203  if (it != fMap->end())
204  {
205  throw error() << "Already have indexed_factory registered for <" << a_index << ">.";
206  }
207  fMap->insert(std::pair< XIndexType, const base_registrar< XBaseType, XArgs... >* >(a_index, a_registrar));
208  LDEBUG( slog_ind_factory_reg, "Registered a indexed_factory for class " << a_index << " at " << (*fMap)[ a_index ] << ", indexed_factory #" << fMap->size()-1 << " for " << this );
209  }
210 
211  template< class XIndexType, class XBaseType, typename ... XArgs >
213  {
214  return fMap->find( a_index ) != fMap->end();
215  }
216 
217  template< class XIndexType, class XBaseType, typename ... XArgs >
219  {
220  LDEBUG( slog_ind_fact, "Removing indexed_factory for class " << a_index << " from " << this );
221  FactoryIt iter = fMap->find( a_index );
222  if( iter != fMap->end() ) fMap->erase( iter );
223  return;
224  }
225 
226  template< class XIndexType, class XBaseType, typename ... XArgs >
228  fMap(new FactoryMap()),
229  f_factory_mutex()
230  {}
231 
232  template< class XIndexType, class XBaseType, typename ... XArgs >
234  {
235  delete fMap;
236  }
237 
238  template< class XIndexType, class XBaseType, typename ... XArgs >
240  {
241  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
242  return fMap->begin();
243  }
244 
245  template< class XIndexType, class XBaseType, typename ... XArgs >
247  {
248  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
249  return fMap->end();
250  }
251 
252  // registrar
253 
254  template< class XIndexType, class XBaseType, class XDerivedType, typename ... XArgs >
256  base_registrar< XBaseType, XArgs... >(),
257  f_index( a_index )
258  {
259  register_class();
260  }
261 
262  template< class XIndexType, class XBaseType, class XDerivedType, typename ... XArgs >
264  {
266  }
267 
268  template< class XIndexType, class XBaseType, class XDerivedType, typename ... XArgs >
270  {
272  return;
273  }
274 
275  template< class XIndexType, class XBaseType, class XDerivedType, typename ... XArgs >
277  {
278  return dynamic_cast< XBaseType* >( new XDerivedType( args... ) );
279  }
280 
281 
282  //*******************************************
283  // Implementations (partial specialization)
284  //*******************************************
285 
286  // indexed_factory
287 
288  template< class XIndexType, class XBaseType >
290  {
291  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
292  return iter->second->create();
293  }
294 
295  template< class XIndexType, class XBaseType >
296  XBaseType* indexed_factory< XIndexType, XBaseType, void >::create( const XIndexType& a_index )
297  {
298  //std::cout << "this indexed_factory (" << this << ") has " << fMap->size() << " entries" << std::endl;
299  //for( FactoryCIt iter = fMap->begin(); iter != fMap->end(); ++iter )
300  //{
301  // std::cout << "this indexed_factory has: " << iter->first << " at " << iter->second << std::endl;
302  //}
303  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
304  FactoryCIt it = fMap->find( a_index );
305  if( it == fMap->end() )
306  {
307  LERROR( slog_ind_fact, "Did not find indexed_factory for <" << a_index << ">." );
308  return nullptr;
309  }
310 
311  return it->second->create();
312  }
313 
314  template< class XIndexType, class XBaseType >
316  {
317  // A local (static) logger is created inside this function to avoid static initialization order problems
318  LOGGER( slog_ind_factory_reg, "indexed_factory-register");
319 
320  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
321  FactoryCIt it = fMap->find(a_index);
322  if (it != fMap->end())
323  {
324  throw error() << "Already have indexed_factory registered for <" << a_index << ">.";
325  return;
326  }
327  fMap->insert(std::pair< std::string, const base_registrar< XIndexType, XBaseType >* >(a_index, a_registrar));
328  LDEBUG( slog_ind_factory_reg, "Registered a indexed_factory for class " << a_index << ", indexed_factory #" << fMap->size()-1 << " for " << this );
329  }
330 
331  template< class XIndexType, class XBaseType >
332  bool indexed_factory< XIndexType, XBaseType, void >::has_class(const XIndexType& a_index ) const
333  {
334  return fMap->find( a_index ) != fMap->end();
335  }
336 
337  template< class XIndexType, class XBaseType >
339  {
340  LDEBUG( slog_ind_fact, "Removing indexed_factory for class " << a_index << " from " << this );
341  FactoryIt iter = fMap->find( a_index );
342  if( iter != fMap->end() ) fMap->erase( iter );
343  return;
344  }
345 
346  template< class XIndexType, class XBaseType >
348  fMap(new FactoryMap()),
349  f_factory_mutex()
350  {}
351 
352  template< class XIndexType, class XBaseType >
354  {
355  delete fMap;
356  }
357 
358  template< class XIndexType, class XBaseType >
360  {
361  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
362  return fMap->begin();
363  }
364 
365  template< class XIndexType, class XBaseType >
367  {
368  std::unique_lock< std::mutex > t_lock( this->f_factory_mutex );
369  return fMap->end();
370  }
371 
372  // registrar
373 
374  template< class XIndexType, class XBaseType, class XDerivedType >
376  base_registrar< XBaseType >(),
377  f_index( a_index )
378  {
379  register_class();
380  }
381 
382  template< class XIndexType, class XBaseType, class XDerivedType >
384  {
386  }
387 
388  template< class XIndexType, class XBaseType, class XDerivedType >
390  {
392  return;
393  }
394 
395  template< class XIndexType, class XBaseType, class XDerivedType >
397  {
398  return dynamic_cast< XBaseType* >( new XDerivedType() );
399  }
400 
401 } /* namespace scarab */
402 #endif /* SCARAB_INDEXED_FACTORY_HH_ */
std::map< XIndexType, const base_registrar< XBaseType, XArgs... > *> FactoryMap
XBaseType * create(XArgs ... args) const
void register_class(const XIndexType &a_index, const base_registrar< XBaseType, XArgs... > *base_registrar)
XBaseType * create(const XIndexType &a_index, XArgs ... args)
LOGGER(mtlog, "authentication")
FactoryMap::value_type FactoryEntry
static indexed_factory< XIndexType, XBaseType, XArgs... > * get_instance()
Definition: singleton.hh:80
#define LERROR(...)
Definition: logger.hh:382
Base class that turns a class into a singleton.
Definition: singleton.hh:43
std::map< XIndexType, const base_registrar< XBaseType > *> FactoryMap
Contains the logger class and macros, based on Kasper&#39;s KLogger class.
FactoryCIt end() const
#define LDEBUG(...)
Definition: logger.hh:377
void remove_class(const XIndexType &a_index)
FactoryMap::iterator FactoryIt
indexed_registrar(const XIndexType &a_index)
virtual XBaseType * create(XArgs ... args) const =0
bool has_class(const XIndexType &a_index) const
FactoryMap::const_iterator FactoryCIt
#define allow_singleton_access(class_name)
Definition: singleton.hh:24
FactoryCIt begin() const