dune-geometry  2.2.0
topologyfactory.hh
Go to the documentation of this file.
00001 #ifndef DUNE_GEOMETRY_TOPOLOGYFACTORY_HH
00002 #define DUNE_GEOMETRY_TOPOLOGYFACTORY_HH
00003 
00004 #include <vector>
00005 #include <map>
00006 
00007 #include <dune/common/fvector.hh>
00008 #include <dune/geometry/genericgeometry/conversion.hh>
00009 #include <dune/geometry/genericgeometry/topologytypes.hh>
00010 
00011 namespace Dune 
00012 {
00013 
00032   template <class Traits>
00033   struct TopologyFactory
00034   {
00035     // extract types from Traits class
00036     static const unsigned int dimension = Traits::dimension;
00037     typedef typename Traits::Key Key;
00038     typedef typename Traits::Object Object;
00039     typedef typename Traits::Factory Factory;
00045     static Object *create(unsigned int topologyId, const Key &key) DUNE_DEPRECATED_MSG("use create(Dune::GeometryType, Key) instead")
00046     {
00047       Object *object;
00048       GenericGeometry::IfTopology< Maker, dimension >::apply( topologyId, key, object );
00049       return object;
00050     }
00052     static Object *create(const Dune::GeometryType &gt, const Key &key) 
00053     {
00054       Object *object;
00055       GenericGeometry::IfTopology< Maker, dimension >::apply( gt.id(), key, object );
00056       return object;
00057     }
00059     template <class Topology>
00060     static Object *create(const Key &key) 
00061     {
00062       return Factory::template createObject<Topology> ( key );
00063     }
00065     static void release( Object *object) 
00066     {
00067       delete object;
00068     }
00069     private:
00070     // Internal maker class used in ifTopology helper
00071     template< class Topology >
00072     struct Maker
00073     {
00074       static void apply ( const Key &key, Object *&object )
00075       {
00076         object = create<Topology>( key );
00077       };
00078     };
00079   };
00080 
00081 
00086   template <class Factory>
00087   struct TopologySingletonFactory
00088   {
00089     static const unsigned int dimension = Factory::dimension;
00090     typedef typename Factory::Key Key;
00091     typedef const typename Factory::Object Object;
00093     static Object *create ( const unsigned int topologyId, const Key &key ) DUNE_DEPRECATED
00094     {
00095       assert( topologyId < numTopologies );
00096       return create( Dune::GeometryType( topologyId, dimension ), key );
00097     }
00099     static Object *create ( const Dune::GeometryType &gt, const Key &key )
00100     {
00101       assert( gt.id() < numTopologies );
00102       return instance().getObject( gt, key );
00103     }
00105     template< class Topology >
00106     static Object *create ( const Key &key )
00107     {
00108       dune_static_assert( (Topology::dimension == dimension),
00109                      "Topology with incompatible dimension used" );
00110       return instance().template getObject< Topology >( key );
00111     }
00113     static void release ( Object *object )
00114     {}
00115   private:
00116     static TopologySingletonFactory &instance ()
00117     {
00118       static TopologySingletonFactory instance;
00119       return instance;
00120     }
00121 
00122     static const unsigned int numTopologies = (1 << dimension);
00123     typedef FieldVector< Object *, numTopologies > Array;
00124     typedef std::map< Key, Array > Storage;
00125 
00126     TopologySingletonFactory ()
00127     {}
00128     ~TopologySingletonFactory ()
00129     {
00130       const typename Storage::iterator end = storage_.end();
00131       for( typename Storage::iterator it = storage_.begin(); it != end; ++it )
00132       {
00133         for( unsigned int topologyId = 0; topologyId < numTopologies; ++topologyId )
00134         {
00135           Object *&object = it->second[ topologyId ];
00136           if( object != 0 )
00137             Factory::release( object );
00138           object = 0;
00139         }
00140       }
00141     }
00142 
00143     Object *&find( const unsigned int topologyId, const Key &key )
00144     {
00145       typename Storage::iterator it = storage_.find( key );
00146       if( it == storage_.end() )
00147         it = storage_.insert( std::make_pair( key, Array( 0 ) ) ).first;
00148       return it->second[ topologyId ];
00149     }
00150 
00151     Object *getObject ( const Dune::GeometryType &gt, const Key &key )
00152     {
00153       Object *&object = find( gt.id(), key );
00154       if( object == 0 )
00155         object = Factory::create( gt, key );
00156       return object;
00157     }
00158 
00159     template< class Topology >
00160     Object *getObject ( const Key &key )
00161     {
00162       Object *&object = find(Topology::id,key);
00163       if( object == 0 )
00164         object = Factory::template create< Topology >( key );
00165       return object;
00166     }
00167     Storage storage_;
00168   };
00169 
00170 }
00171 
00172 #endif // #ifndef DUNE_GEOMETRY_TOPOLOGYFACTORY_HH