GenericFactory.H

Go to the documentation of this file.
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: */
Generated on Sun May 8 08:40:39 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3