factory.h

Go to the documentation of this file.
00001 
00005 
00006 //
00007 // Copyright (c) 1999-2004 California Institute of Technology
00008 // Copyright (c) 2004-2007 University of Southern California
00009 // Rob Peters <rjpeters at usc dot edu>
00010 //
00011 // created: Sat Jun 26 23:40:55 1999
00012 // commit: $Id: factory.h 10097 2007-08-07 19:08:27Z rjpeters $
00013 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/rutz/factory.h $
00014 //
00015 // --------------------------------------------------------------------
00016 //
00017 // This file is part of GroovX.
00018 //   [http://ilab.usc.edu/rjpeters/groovx/]
00019 //
00020 // GroovX is free software; you can redistribute it and/or modify it
00021 // under the terms of the GNU General Public License as published by
00022 // the Free Software Foundation; either version 2 of the License, or
00023 // (at your option) any later version.
00024 //
00025 // GroovX is distributed in the hope that it will be useful, but
00026 // WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU General Public License
00031 // along with GroovX; if not, write to the Free Software Foundation,
00032 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
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     // typedefs
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           // note that we must call try_fallback() with our mutex
00183           // UN-locked because the intention is that the fallback
00184           // function will try do something to cause a new entry to be
00185           // inserted into this very factory object; that insertion
00186           // will require locking the mutex so if we have the mutex
00187           // locked here we will end up with a deadlock:
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 } // end namespace rutz
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

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:40 2008 by Doxygen version 1.5.5.