00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00035
00036 #ifndef GROOVX_RUTZ_FACTORY_H_UTC20050626084020_DEFINED
00037 #define GROOVX_RUTZ_FACTORY_H_UTC20050626084020_DEFINED
00038
00039 #include "rutz/assocarray.h"
00040 #include "rutz/demangle.h"
00041 #include "rutz/fileposition.h"
00042 #include "rutz/mutex.h"
00043 #include "rutz/shared_ptr.h"
00044 #include "rutz/traits.h"
00045
00046 #include <typeinfo>
00047
00048 namespace rutz
00049 {
00050 class fstring;
00051
00053
00056 template <class T>
00057 class creator_base
00058 {
00059 public:
00060 typedef T base_t;
00061
00063 virtual ~creator_base() {}
00064
00066 virtual creator_base* clone() const = 0;
00067
00069 virtual base_t create() = 0;
00070 };
00071
00072
00074
00077 template <class base_t, class derived_t>
00078 class creator_from_func : public rutz::creator_base<base_t>
00079 {
00080 public:
00082 typedef derived_t (*creator_func_t) ();
00083
00085 creator_from_func(creator_func_t func) :
00086 rutz::creator_base<base_t>(), m_creator_func(func) {}
00087
00089 virtual rutz::creator_base<base_t>* clone() const
00090 { return new creator_from_func<base_t, derived_t>(*this); }
00091
00093 virtual base_t create() { return base_t(m_creator_func()); }
00094
00095 private:
00096 creator_func_t m_creator_func;
00097 };
00098
00099
00101 class factory_fallback
00102 {
00103 public:
00105 factory_fallback() throw();
00106
00108 virtual ~factory_fallback() throw();
00109
00111 virtual void try_fallback(const rutz::fstring& key) const = 0;
00112 };
00113
00115 class factory_base
00116 {
00117 public:
00118 typedef void (fallback_t)(const rutz::fstring&);
00119
00121 factory_base() throw();
00122
00124 virtual ~factory_base() throw();
00125
00127 void set_fallback(rutz::shared_ptr<factory_fallback> f);
00128
00130 void set_fallback(fallback_t* fptr);
00131
00133 void try_fallback(const rutz::fstring& key) const;
00134
00135 private:
00136 rutz::shared_ptr<factory_fallback> m_fallback;
00137 };
00138
00139
00141
00154 template <class T>
00155 class factory
00156 {
00157 public:
00158
00159
00160 typedef factory_base::fallback_t fallback_t;
00161 typedef T base_t;
00162
00163 private:
00164 rutz::factory_base m_base;
00165 rutz::assoc_array<rutz::creator_base<base_t> > m_map;
00166 mutable pthread_mutex_t m_mutex;
00167
00168 protected:
00170 rutz::creator_base<base_t>*
00171 find_creator(const rutz::fstring& key) const
00172 {
00173 rutz::creator_base<base_t>* creator = 0;
00174
00175 {
00176 GVX_MUTEX_LOCK(&m_mutex);
00177 creator = m_map.get_ptr_for_key(key);
00178 }
00179
00180 if (creator == 0)
00181 {
00182
00183
00184
00185
00186
00187
00188 m_base.try_fallback(key);
00189
00190 {
00191 GVX_MUTEX_LOCK(&m_mutex);
00192 creator = m_map.get_ptr_for_key(key);
00193 }
00194 }
00195
00196 return creator;
00197 }
00198
00199 public:
00201
00210 factory(const char* keydescr = "object type", bool nocase = false)
00211 : m_base(), m_map(keydescr, nocase), m_mutex()
00212 {
00213 pthread_mutex_init(&m_mutex, (pthread_mutexattr_t*) 0);
00214 }
00215
00217 virtual ~factory() throw()
00218 {
00219 pthread_mutex_destroy(&m_mutex);
00220 }
00221
00223
00225 const char* register_creator(rutz::creator_base<base_t>* creator,
00226 const char* name)
00227 {
00228 GVX_MUTEX_LOCK(&m_mutex);
00229
00230 m_map.set_ptr_for_key(name, creator);
00231
00232 return name;
00233 }
00234
00236
00239 template <class derived_t>
00240 const char* register_creator(derived_t (*func) (),
00241 const char* key = 0)
00242 {
00243 GVX_MUTEX_LOCK(&m_mutex);
00244
00245 if (key == 0)
00246 key = rutz::demangled_name
00247 (typeid(typename rutz::type_traits<derived_t>::pointee_t));
00248
00249 m_map.set_ptr_for_key
00250 (key, new rutz::creator_from_func<base_t, derived_t>(func));
00251
00252 return key;
00253 }
00254
00256
00258 void register_alias(const char* orig_key, const char* alias_key)
00259 {
00260 GVX_MUTEX_LOCK(&m_mutex);
00261
00262 rutz::creator_base<base_t>* creator =
00263 m_map.get_ptr_for_key(orig_key);
00264
00265 if (creator != 0)
00266 {
00267 m_map.set_ptr_for_key(alias_key, creator->clone());
00268 }
00269 }
00270
00272 bool is_valid_key(const char* key) const
00273 {
00274 return (this->find_creator(key) != 0);
00275 }
00276
00278 rutz::fstring get_known_keys(const char* sep) const
00279 {
00280 GVX_MUTEX_LOCK(&m_mutex);
00281
00282 return m_map.get_known_keys(sep);
00283 }
00284
00286
00288 base_t new_object(const rutz::fstring& type) const
00289 {
00290 rutz::creator_base<base_t>* creator = this->find_creator(type);
00291
00292 if (creator == 0) return base_t();
00293
00294 return creator->create();
00295 }
00296
00298
00300 base_t new_checked_object(const rutz::fstring& type) const
00301 {
00302 rutz::creator_base<base_t>* creator = this->find_creator(type);
00303
00304 if (creator == 0)
00305 {
00306 GVX_MUTEX_LOCK(&m_mutex);
00307
00308 m_map.throw_for_key(type, SRC_POS);
00309 }
00310
00311 return creator->create();
00312 }
00313
00315 void set_fallback(rutz::shared_ptr<factory_fallback> f)
00316 {
00317 GVX_MUTEX_LOCK(&m_mutex);
00318
00319 m_base.set_fallback(f);
00320 }
00321
00323 void set_fallback(fallback_t* fptr)
00324 {
00325 GVX_MUTEX_LOCK(&m_mutex);
00326
00327 m_base.set_fallback(fptr);
00328 }
00329 };
00330
00331 }
00332
00333
00334 static const char __attribute__((used)) vcid_groovx_rutz_factory_h_utc20050626084020[] = "$Id: factory.h 10097 2007-08-07 19:08:27Z rjpeters $ $HeadURL: file:
00335 #endif // !GROOVX_RUTZ_FACTORY_H_UTC20050626084020_DEFINED