1 #ifndef DUNE_FEM_SINGLETONLIST_HH 2 #define DUNE_FEM_SINGLETONLIST_HH 3 4 //- System includes 5 #include <cassert> 6 #include <vector> 7 #include <string> 8 #include <list> 9 #include <iostream> 10 #include <type_traits> 11 #include <utility> 12 13 //- dune-fem includes 14 #include <dune/fem/misc/threads/threadmanager.hh> 15 #include <dune/fem/storage/singleton.hh> 16 17 namespace Dune 18 { 19 20 namespace Fem 21 { 22 23 template< class Key, class Object > 24 struct DefaultSingletonFactory 25 { createObjectDune::Fem::DefaultSingletonFactory26 static Object *createObject ( const Key &key ) 27 { 28 return new Object( key ); 29 } 30 deleteObjectDune::Fem::DefaultSingletonFactory31 static void deleteObject ( Object *object ) 32 { 33 delete object; 34 } 35 }; 36 37 38 /** \class SingletonList 39 * \ingroup HelperClasses 40 * \brief Singleton list for key/object pairs 41 * 42 * A singleton list guarantees that for any valid key at most one object is 43 * created. 44 * 45 * \param Key type of keys 46 * \param Object type of objects 47 * \param Factory factory class creating objects from keys. The default 48 * just passes the key to the object's constructor. 49 */ 50 template< class Key, class Object, 51 class Factory = DefaultSingletonFactory< Key, Object > > 52 class SingletonList 53 { 54 typedef SingletonList< Key, Object, Factory > ThisType; 55 56 public: 57 typedef Key KeyType; 58 typedef Object ObjectType; 59 typedef Factory FactoryType; 60 61 typedef std :: pair< ObjectType * , unsigned int * > ValueType; 62 typedef std :: pair< KeyType, ValueType > ListObjType; 63 64 struct Deleter 65 { operator ()Dune::Fem::SingletonList::Deleter66 void operator() ( ObjectType *p ) const { ThisType::removeObject( *p ); } 67 }; 68 69 private: 70 typedef std :: list< ListObjType > ListType; 71 typedef typename ListType :: iterator ListIteratorType; 72 73 class SingletonListStorage; 74 75 public: 76 SingletonList () = delete; 77 SingletonList ( const ThisType& ) = delete; 78 79 //! list that store pairs of key/object pointers 80 //! singleton list singletonList()81 static ListType &singletonList () 82 { 83 //static SingletonListStorage s; 84 SingletonListStorage& s = Singleton< SingletonListStorage >::instance(); 85 86 //! list that store pairs of key/object pointers 87 return s.singletonList(); 88 } 89 90 //! return reference to the object for given key. 91 //! If the object does not exist, then it is created first, otherwise the 92 //! reference counter is increased. 93 template< class... Args > getObject(const KeyType & key,Args &&...args)94 static auto getObject( const KeyType &key, Args &&... args ) 95 -> std::enable_if_t< std::is_same< decltype( FactoryType::createObject( key, std::forward< Args >( args )... ) ), ObjectType * >::value, ObjectType & > 96 { 97 // make sure this method is only called in single thread mode 98 assert( Fem :: ThreadManager :: singleThreadMode() ); 99 100 ValueType objValue = getObjFromList( key ); 101 102 // if object exists, increase reference count and return it 103 if( objValue.first ) 104 { 105 ++( *(objValue.second) ); 106 return *(objValue.first); 107 } 108 109 // object does not exist. Create it with reference count of 1 110 ObjectType *object = FactoryType::createObject( key, std::forward< Args >( args )... ); 111 assert( object ); 112 ValueType value( object, new unsigned int( 1 ) ); 113 ListObjType tmp( key, value ); 114 singletonList().push_back( tmp ); 115 return *object; 116 } 117 118 //! decrease ref counter for this object, 119 //! if ref counter is zero, object is deleted removeObject(const ObjectType & object)120 inline static void removeObject ( const ObjectType &object ) 121 { 122 // make sure this method is only called in single thread mode 123 assert( Fem :: ThreadManager :: singleThreadMode() ); 124 125 ListIteratorType end = singletonList().end(); 126 for( ListIteratorType it = singletonList().begin(); it != end; ++it ) 127 { 128 if( (*it).second.first == &object ) 129 { 130 eraseItem( it ); 131 return; 132 } 133 } 134 135 std :: cerr << "Object could not be deleted, " 136 << "because it is not in the list anymore!" << std :: endl; 137 } 138 139 // return pair < Object * , refCounter *> getObjFromList(const KeyType & key)140 inline static ValueType getObjFromList( const KeyType &key ) 141 { 142 ListIteratorType endit = singletonList().end(); 143 for(ListIteratorType it = singletonList().begin(); it!=endit; ++it) 144 { 145 if( (*it).first == key ) 146 { 147 return (*it).second; 148 } 149 } 150 return ValueType( (ObjectType *)0, (unsigned int *)0 ); 151 } 152 153 protected: eraseItem(ListIteratorType & it)154 static void eraseItem( ListIteratorType &it ) 155 { 156 ValueType value = (*it).second; 157 unsigned int &refCount = *(value.second); 158 159 assert( refCount > 0 ); 160 if( (--refCount) == 0 ) 161 deleteItem( it ); 162 } 163 164 private: deleteItem(ListIteratorType & it)165 static void deleteItem(ListIteratorType & it) 166 { 167 ValueType val = (*it).second; 168 // remove from list 169 singletonList().erase( it ); 170 // delete objects 171 FactoryType :: deleteObject( val.first ); 172 delete val.second; 173 } 174 }; // end SingletonList 175 176 177 template< class Key, class Object, class Factory > 178 class SingletonList< Key, Object, Factory > :: SingletonListStorage 179 { 180 typedef SingletonListStorage ThisType; 181 182 protected: 183 ListType singletonList_; 184 185 public: SingletonListStorage()186 inline SingletonListStorage () 187 : singletonList_() 188 {} 189 ~SingletonListStorage()190 inline ~SingletonListStorage () 191 { 192 while( !singletonList().empty() ) 193 deleteItem( singletonList().begin() ); 194 } 195 singletonList()196 ListType &singletonList () 197 { 198 return singletonList_; 199 } 200 deleteItem(const ListIteratorType & it)201 void deleteItem ( const ListIteratorType &it ) 202 { 203 ValueType val = (*it).second; 204 // remove from list 205 singletonList().erase( it ); 206 // delete objects 207 FactoryType :: deleteObject( val.first ); 208 delete val.second; 209 } 210 }; 211 212 } // namespace Fem 213 214 } // namespace Dune 215 216 #endif // #ifndef DUNE_FEM_SINGLETONLIST_HH 217