factory.h
Go to the documentation of this file.00001
00002
00003
00004
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
00034
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
00052
00053
00054
00055
00056 template <class T>
00057 class creator_base
00058 {
00059 public:
00060 typedef T base_t;
00061
00062
00063 virtual ~creator_base() {}
00064
00065
00066 virtual creator_base* clone() const = 0;
00067
00068
00069 virtual base_t create() = 0;
00070 };
00071
00072
00073
00074
00075
00076
00077 template <class base_t, class derived_t>
00078 class creator_from_func : public rutz::creator_base<base_t>
00079 {
00080 public:
00081
00082 typedef derived_t (*creator_func_t) ();
00083
00084
00085 creator_from_func(creator_func_t func) :
00086 rutz::creator_base<base_t>(), m_creator_func(func) {}
00087
00088
00089 virtual rutz::creator_base<base_t>* clone() const
00090 { return new creator_from_func<base_t, derived_t>(*this); }
00091
00092
00093 virtual base_t create() { return base_t(m_creator_func()); }
00094
00095 private:
00096 creator_func_t m_creator_func;
00097 };
00098
00099
00100
00101 class factory_fallback
00102 {
00103 public:
00104
00105 factory_fallback() throw();
00106
00107
00108 virtual ~factory_fallback() throw();
00109
00110
00111 virtual void try_fallback(const rutz::fstring& key) const = 0;
00112 };
00113
00114
00115 class factory_base
00116 {
00117 public:
00118 typedef void (fallback_t)(const rutz::fstring&);
00119
00120
00121 factory_base() throw();
00122
00123
00124 virtual ~factory_base() throw();
00125
00126
00127 void set_fallback(rutz::shared_ptr<factory_fallback> f);
00128
00129
00130 void set_fallback(fallback_t* fptr);
00131
00132
00133 void try_fallback(const rutz::fstring& key) const;
00134
00135 private:
00136 rutz::shared_ptr<factory_fallback> m_fallback;
00137 };
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
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:
00169
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:
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
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
00216
00217 virtual ~factory() throw()
00218 {
00219 pthread_mutex_destroy(&m_mutex);
00220 }
00221
00222
00223
00224
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
00235
00236
00237
00238
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
00255
00256
00257
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
00271
00272 bool is_valid_key(const char* key) const
00273 {
00274 return (this->find_creator(key) != 0);
00275 }
00276
00277
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
00285
00286
00287
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
00297
00298
00299
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
00314
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
00322
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 8274 2007-04-19 17:44:48Z rjpeters $ $HeadURL: svn:
00335 #endif // !GROOVX_RUTZ_FACTORY_H_UTC20050626084020_DEFINED