00001 /*!@file GenericUtils/GenericFactory.H A generic Factory*/ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: David J. Berg <dberg@usc.edu> 00034 // $HeadURL:svn://ilab.usc.edu/trunk/saliency/src/GenericUtils/GenericFactory.H$ 00035 00036 #include "Util/log.H" 00037 00038 #include <pthread.h> 00039 #include <map> 00040 #include <string> 00041 00042 #ifndef UTIL_GENERICFACTORY_H_DEFINED 00043 #define UTIL_GENERICFACTORY_H_DEFINED 00044 00045 // ###################################################################### 00046 // A default policy for error handling in a GenericFactory (see 00047 // below). Type specific policies should be added in the type specific 00048 // files. An ErrorPolicy type should implement the following 00049 // functions: 00050 // 00051 // ReturnType* createError(); // called if 'GenericFactory::create()' 00052 // // fails to find the key 00053 // 00054 // void registerError(); // called if nothing is added when 'registerCreator()' 00055 // // is called 00056 // ###################################################################### 00057 // In the default error policy, errors during object will cause LFATAL 00058 // ###################################################################### 00059 template<class ReturnType, typename KeyType> 00060 struct DefaultFactoryError 00061 { 00062 //constructor/destructor 00063 DefaultFactoryError() { }; 00064 ~DefaultFactoryError() { }; 00065 00066 //possibly do something if registerCreator fails to add an entry 00067 void registerError() const 00068 { }; 00069 00070 //return an error if create() fails to find the 'key' 00071 ReturnType* createError(const KeyType& key) const 00072 { 00073 LFATAL("The Factory produced an error and no object was returned " 00074 "because the key could not be found."); 00075 return NULL; 00076 }; 00077 }; 00078 00079 // ###################################################################### 00080 // In the strict error policy, any error will cause LFATAL 00081 // ###################################################################### 00082 template<class ReturnType, typename KeyType> 00083 struct StrictFactoryError 00084 { 00085 //constructor/destructor 00086 StrictFactoryError() { }; 00087 ~StrictFactoryError() { }; 00088 00089 //possibly do something if registerCreator fails to add an entry 00090 void registerError() const 00091 { 00092 LFATAL("The key/creator pair could not be registered. " 00093 "It is likely this key alread exists"); 00094 }; 00095 00096 //return an error if create() fails to find the 'key' 00097 ReturnType* createError(const KeyType& key) const 00098 { 00099 LFATAL("The Factory produced an error and no object was returned " 00100 "because the key could not be found."); 00101 return NULL; 00102 }; 00103 }; 00104 00105 // ###################################################################### 00106 // define a do nothing error policy for factories 00107 // ###################################################################### 00108 template<class ReturnType, typename KeyType> 00109 struct DoNothingFactoryError 00110 { 00111 //constructor/destructor 00112 DoNothingFactoryError() { }; 00113 ~DoNothingFactoryError() { }; 00114 00115 //possibly do something if registerCreator fails to add an entry 00116 void registerError() const 00117 { }; 00118 00119 //return an error if create() fails to find the 'key' 00120 ReturnType* createError(const KeyType& key) const 00121 { return NULL; }; 00122 }; 00123 00124 // ###################################################################### 00125 // A reusable factory. This class is intended to simplify the creation 00126 // of objects from simple 'keys' (like a std::string representing the 00127 // name of the object). The objects stored in the factory should all 00128 // derive from a common base class. The user should call 00129 // registerCreator() to make an association between a key and a 00130 // pointer to a function (or a functor - especially useful for 00131 // including parameters, see FactoryHelper namespace below) that can 00132 // actually create the object. The pointer to function (or functor) 00133 // should allocate memory, and configure the desired object returning 00134 // a pointer to the objects base class. A call to 00135 // ReusableFactory::create() will then create the appropriate object 00136 // and return a pointer to the base class. 00137 // 00138 // Additionally, the createConvert<>() template function is provided 00139 // which will attempt to create the object, and then covert it to the 00140 // desired type before returning. The template argument can be a 00141 // pointer or non-pointer type. If the template argument is a pointer, 00142 // a call to createConvert<>() will call dynamic_cast and return a 00143 // pointer to the desired type (or fail an error). If the template 00144 // argument is a non-pointer then the object will be dynamic_cast, 00145 // dereferenced, copied with the assignment operator, and finally the 00146 // copy will be returned. 00147 // 00148 // ###################################################################### 00149 // templated types are as follows: 00150 // ###################################################################### 00151 // ReturnType : the type to return from the factory (usually a base 00152 // class), create will return a ReturnType*. 00153 // 00154 // KeyType : the type to be used as the unique key for each objecy 00155 // type (any type that supports operator<() ) 00156 // 00157 // TypeCreator : the type of the object creator mechanism. This could 00158 // be anything that supports 'ReturnType* operator()()' (usually a 00159 // pointer to a function, but could also be a non-pointer functor). 00160 // 00161 // ErrorType : the class that will handle errors in the factory. Such 00162 // a class should implment the following functions: 00163 // 00164 // ReturnType* createError(); // called if 'GenericFactory::create()' 00165 // // fails to find the key 00166 // 00167 // void registerError(); // called if nothing is added when 00168 // // 'registerCreator()' is called 00169 // 00170 // ###################################################################### 00171 // Some example usages: Say we have a Shape base class, with derived 00172 // classes Circle and Square, each having there own creation function. 00173 // ###################################################################### 00174 // //Register a string key with pointers to functions 00175 // factory.add("circle", &createCircle); 00176 // factory.add("square", &createSquare); 00177 00178 // create using factory helper function, create, to auto insert a 00179 // creation function 00180 // factory.add("rectangle", &FactoryHelper::create<Shape,Rectangle>()); 00181 // 00182 // //create a circle and return a pointer to the base class 00183 // Shape* shape = factory.create("circle"); 00184 // 00185 // //create a circle and return a pointer to a circle 00186 // Circle* shape1 = factory.createConvert<Circle*>("circle"); 00187 // 00188 // //create a square and return it 00189 // Square shape2 = factory.createConvert<Square>("square"); 00190 // 00191 // //will error : no registered key 00192 // Shape* shape = factory.create("triangle"); 00193 // 00194 // //will error : cannot convert Cirlce* to Square* 00195 // Square* shape1 = factory.createConvert<Square*>("circle"); 00196 // 00197 // ###################################################################### 00198 // Note: This implementation uses std::map, which is not ideal for many 00199 // situations - particularly where you need fast lookups (for example 00200 // creating objects in the main loop of your program). Another 00201 // implementation could have an additional template parameter for the 00202 // internal container to use. 00203 //###################################################################### 00204 template<class ReturnType, 00205 typename KeyType = std::string, 00206 typename TypeCreator = ReturnType* (*)(), 00207 template<class, typename> class ErrorPolicy = DefaultFactoryError 00208 > 00209 class ReusableFactory : public ErrorPolicy<ReturnType, KeyType> 00210 { 00211 public: 00212 ReusableFactory() : ErrorPolicy<ReturnType, KeyType>(), itsMap() { }; 00213 ~ReusableFactory() { }; 00214 00215 //a read/write iterator 00216 typedef typename std::map<KeyType, TypeCreator>::iterator iterator; 00217 00218 // ###################################################################### 00219 // register an key/object creation function pair and return 'true' 00220 // if something was added. If nothing was added, createError() is 00221 // called and false is returned 00222 // ###################################################################### 00223 const bool add(const KeyType& key, TypeCreator func) 00224 { 00225 const bool added = (itsMap.insert(make_pair(key, func))).second; 00226 if (added == false) 00227 this->registerError(); 00228 00229 return added; 00230 } 00231 00232 // ###################################################################### 00233 // unregister an object function and return whether we removed anything 00234 // ###################################################################### 00235 const bool remove(const KeyType& key) 00236 { 00237 return (itsMap.erase(key) > 0); 00238 } 00239 00240 // ###################################################################### 00241 // create the appropriate object from a registered key and return a 00242 // pointer to the base class (ReturnType) 00243 // ###################################################################### 00244 ReturnType* create(const KeyType& key) const 00245 { 00246 typename Map::const_iterator iter = itsMap.find(key); 00247 if (iter != itsMap.end()) 00248 return (iter->second)(); 00249 00250 return this->createError(key); 00251 } 00252 00253 // ###################################################################### 00254 // get a read/write iterator to the first key/creator pair. Returns 00255 // a std::pair where 'first' is the key and 'Second' is the value 00256 // ###################################################################### 00257 iterator begin() 00258 { 00259 return itsMap.begin(); 00260 }; 00261 00262 // ###################################################################### 00263 // get a read/write iterator to 1 past the last key/creator pair. 00264 // ###################################################################### 00265 iterator end() 00266 { 00267 return itsMap.end(); 00268 }; 00269 00270 // ###################################################################### 00271 // create the appropriate object from a registered key as with create(), 00272 // but before returning attempt to convert to the templated type. 00273 // ###################################################################### 00274 template<class ConvertType> 00275 ConvertType createConvert(const KeyType& key) 00276 { 00277 return convertHelper<ConvertType>(key, Int2Type<PntrTraits<ConvertType>::isPointer>()); 00278 } 00279 00280 private: 00281 //prevent copy and assignment 00282 ReusableFactory(const ReusableFactory& rhs); 00283 ReusableFactory& operator=(const ReusableFactory& rhs); 00284 00285 // ###################################################################### 00286 // typedefs and helper classes 00287 // ###################################################################### 00288 //useful typedefs 00289 typedef typename std::map<KeyType, TypeCreator> Map; 00290 00291 //a helper class to determine if ConvertType is a pointer 00292 template <typename T> struct PntrTraits{ enum {isPointer = false}; }; 00293 template <typename T> struct PntrTraits<T*>{ enum {isPointer = true}; }; 00294 00295 //an empty helper class to 'typeify' an integer 00296 template <int input> class Int2Type { }; 00297 00298 // ###################################################################### 00299 // for when ConvertType in createConvert() is a pointer 00300 // ###################################################################### 00301 template<class ConvertType> 00302 ConvertType convertHelper(const KeyType& key, Int2Type<true>) 00303 { 00304 ReturnType* basep = this->create(key); 00305 00306 //dynamic cast from our base type * to the convert type * 00307 //(ConverType will be a pointer) 00308 ConvertType convp = dynamic_cast<ConvertType>(basep); 00309 00310 if (convp != NULL) 00311 return convp; 00312 00313 LFATAL("Failed to covert to the desired type."); 00314 return NULL; 00315 } 00316 00317 // ###################################################################### 00318 //for when ConvertType in createConvert() is a non-pointer 00319 // ###################################################################### 00320 template<class ConvertType> 00321 ConvertType convertHelper(const KeyType& key, Int2Type<false>) 00322 { 00323 ReturnType* basep = this->create(key); 00324 00325 //dynamic cast from our base type * to the convert type * 00326 //(ConvertType will be non-pointer) 00327 ConvertType* convp = dynamic_cast<ConvertType*>(basep); 00328 00329 ConvertType temp = *convp; //copy the object 00330 delete convp;//clean up the temporary memory 00331 return temp; 00332 } 00333 00334 //the map to hold registered key-function pairs 00335 Map itsMap; 00336 }; 00337 00338 // ###################################################################### 00339 // GenericFactory is a thread-safe singleton class that extends 00340 // ReusableFactory. A singleton is a design pattern that supports 00341 // global access to a unique object (only one can exist in your 00342 // program). The main advantage of this pattern for a factory is that 00343 // is supplies a global access point to a static structure, which 00344 // means we can register our classes in there own .C or .H 00345 // file. Besides being extremely convenient, it eliminates the 00346 // dependecy bottleneck of a non-static factory, and no additional 00347 // source files need be edited when adding a new class to the 00348 // registry. 00349 // 00350 // Building on the example in ReusableFactory (above): 00351 // 00352 // //Register a string key with pointers to different shape creation 00353 // //functions. This could in, for instance, 'Shapes.C' 00354 // namespace 00355 // { 00356 // typedef GenericFactory<Shape> ShapeFactory; 00357 // struct RegisterShapes 00358 // { 00359 // RegisterShapes() 00360 // { 00361 // Using namespace FactoryHelper; 00362 // ShapeFactory::instance().add("Circle", &createCircle); 00363 // ShapeFactory::instance().add("Square", &createSquare); 00364 // ShapeFactory::instance().add("Rectangle", &create<Shape,Rectangle>()); 00365 // } 00366 // }; 00367 // static RegisterShapes Register; 00368 // } 00369 00370 // //then in our 'main' we (or someone else) can use them without 00371 // //ever thinking about registering them. 00372 // ShapeFactory::instance().add("circle", &createCircle); 00373 // ShapeFactory::instance().add("square", &createSquare); 00374 // 00375 // //create a circle and return a pointer to the base class 00376 // Shape* shape = ShapeFactory::instance().create("circle"); 00377 // 00378 //###################################################################### 00379 //Programmer Note: 00380 //We never 'delete' the object we create in Instance(), but this is 00381 //not a memory leak. The object is intended to stay alive for the 00382 //duration of the program, we never lose reference to it, no new 00383 //memory is being created and the OS will deallocate the memory upon 00384 //program termination. 00385 // 00386 //However, it would be dangerous to allow another classes destructor 00387 //to depend on GenericFactory operations, as the order of destruction 00388 //of static elements is not gauranteed, and the Singleton may not 00389 //exist. 00390 // 00391 //The double check and lock paradigm is used for thread safety. This 00392 //should work on most or all systems but is not garaunteed. 00393 //###################################################################### 00394 template<class ReturnType, 00395 typename KeyType = std::string, 00396 typename TypeCreator = ReturnType* (*)(), 00397 template<class, typename> class ErrorPolicy = DefaultFactoryError 00398 > 00399 class GenericFactory 00400 { 00401 private: 00402 //a helper class to deal with the mutex 00403 class Lock 00404 { 00405 pthread_mutex_t tmut; //a mutex to lock creation 00406 public: 00407 Lock() { pthread_mutex_init(&tmut, NULL); }; 00408 ~Lock() { pthread_mutex_destroy(&tmut); }; 00409 bool lock() {return (0 == pthread_mutex_lock(&tmut)) ? 1 : 0; }; 00410 bool unlock() {return (0 == pthread_mutex_unlock(&tmut)) ? 1 : 0; }; 00411 }; 00412 00413 GenericFactory(); 00414 ~GenericFactory(); 00415 GenericFactory(const GenericFactory&); 00416 GenericFactory& operator=(const GenericFactory&); 00417 00418 typedef ReusableFactory<ReturnType, KeyType, TypeCreator, ErrorPolicy> FactoryType; 00419 typedef FactoryType* InstanceType; 00420 00421 static InstanceType itsInstance; // The one and only instance 00422 static volatile bool isCreated; // see if we are created 00423 static Lock itsLocker; //a mutex to lock our instance 00424 00425 public: 00426 static FactoryType& instance() // Unique point of access 00427 { 00428 //double checked lock paradim 00429 if (!isCreated) 00430 { 00431 if (!itsLocker.lock()) 00432 LFATAL("Mutex locking error"); 00433 00434 if (!isCreated) 00435 { 00436 itsInstance = new FactoryType(); 00437 isCreated = true; 00438 } 00439 00440 if (!itsLocker.unlock()) 00441 LFATAL("Mutex unlocking error"); 00442 00443 } 00444 return *itsInstance; 00445 } 00446 }; 00447 00448 //###################################################################### 00449 // FactoryHelper is a set of utilities to be used with GenericFactory 00450 //###################################################################### 00451 namespace FactoryHelper 00452 { 00453 //helper function to make a creation functions 00454 //###################################################################### 00455 template <class BaseType, class DerivedType> 00456 BaseType* create() {return new DerivedType; }; 00457 } 00458 00459 //###################################################################### 00460 // static variable initialization 00461 //###################################################################### 00462 //initialize our itsInstance 00463 template<class ReturnType, 00464 typename KeyType, 00465 typename TypeCreator, 00466 template<class, typename> class ErrorPolicy> 00467 typename GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::InstanceType GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::itsInstance = NULL; 00468 00469 //initialize isCreated 00470 template<class ReturnType, 00471 typename KeyType, 00472 typename TypeCreator, 00473 template<class, typename> class ErrorPolicy> 00474 volatile bool GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::isCreated = false; 00475 00476 //initialize the locker 00477 template<class ReturnType, 00478 typename KeyType, 00479 typename TypeCreator, 00480 template<class, typename> class ErrorPolicy> 00481 typename GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::Lock GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::itsLocker = typename GenericFactory<ReturnType,KeyType,TypeCreator,ErrorPolicy>::Lock(); 00482 00483 #endif 00484 // ###################################################################### 00485 /* So things look consistent in everyone's emacs... */ 00486 /* Local Variables: */ 00487 /* indent-tabs-mode: nil */ 00488 /* End: */