DUNE-FEM (unstable)

singletonlist.hh
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/mpimanager.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  {
26  static Object *createObject ( const Key &key )
27  {
28  return new Object( key );
29  }
30 
31  static void deleteObject ( Object *object )
32  {
33  delete object;
34  }
35  };
36 
37 
50  template< class Key, class Object,
51  class Factory = DefaultSingletonFactory< Key, Object > >
53  {
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  {
66  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 
81  static ListType &singletonList ()
82  {
83  //static SingletonListStorage s;
84  SingletonListStorage& s = Singleton< SingletonListStorage >::instance();
85 
87  return s.singletonList();
88  }
89 
93  template< class... 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  ValueType objValue = getObjFromList( key );
98 
99  // if object exists, increase reference count and return it
100  if( objValue.first )
101  {
102  ++( *(objValue.second) );
103  return *(objValue.first);
104  }
105 
106  // make sure this part is only called in single thread mode
107  if( ! Fem :: MPIManager :: singleThreadMode() )
108  {
109  DUNE_THROW(SingleThreadModeError, "SingletonList::getObject: only call in single thread mode!");
110  }
111 
112  // object does not exist. Create it with reference count of 1
113  ObjectType *object = FactoryType::createObject( key, std::forward< Args >( args )... );
114  assert( object );
115  ValueType value( object, new unsigned int( 1 ) );
116  ListObjType tmp( key, value );
117  singletonList().push_back( tmp );
118  return *object;
119  }
120 
123  inline static void removeObject ( const ObjectType &object )
124  {
125  // make sure this method is only called in single thread mode
126  if( ! Fem :: MPIManager :: singleThreadMode() )
127  {
128  DUNE_THROW(SingleThreadModeError, "SingletonList::removeObject: only call in single thread mode!");
129  }
130 
131  ListIteratorType end = singletonList().end();
132  for( ListIteratorType it = singletonList().begin(); it != end; ++it )
133  {
134  if( (*it).second.first == &object )
135  {
136  eraseItem( it );
137  return;
138  }
139  }
140 
141  std :: cerr << "Object could not be deleted, "
142  << "because it is not in the list anymore!" << std :: endl;
143  }
144 
145  // return pair < Object * , refCounter *>
146  inline static ValueType getObjFromList( const KeyType &key )
147  {
148  ListIteratorType endit = singletonList().end();
149  for(ListIteratorType it = singletonList().begin(); it!=endit; ++it)
150  {
151  if( (*it).first == key )
152  {
153  return (*it).second;
154  }
155  }
156  return ValueType( (ObjectType *)0, (unsigned int *)0 );
157  }
158 
159  protected:
160  static void eraseItem( ListIteratorType &it )
161  {
162  ValueType value = (*it).second;
163  unsigned int &refCount = *(value.second);
164 
165  assert( refCount > 0 );
166  if( (--refCount) == 0 )
167  deleteItem( it );
168  }
169 
170  private:
171  static void deleteItem(ListIteratorType & it)
172  {
173  ValueType val = (*it).second;
174  // remove from list
175  singletonList().erase( it );
176  // delete objects
177  FactoryType :: deleteObject( val.first );
178  delete val.second;
179  }
180  }; // end SingletonList
181 
182 
183  template< class Key, class Object, class Factory >
184  class SingletonList< Key, Object, Factory > :: SingletonListStorage
185  {
186  typedef SingletonListStorage ThisType;
187 
188  protected:
189  ListType singletonList_;
190 
191  public:
192  inline SingletonListStorage ()
193  : singletonList_()
194  {}
195 
196  inline ~SingletonListStorage ()
197  {
198  while( !singletonList().empty() )
199  deleteItem( singletonList().begin() );
200  }
201 
202  ListType &singletonList ()
203  {
204  return singletonList_;
205  }
206 
207  void deleteItem ( const ListIteratorType &it )
208  {
209  ValueType val = (*it).second;
210  // remove from list
211  singletonList().erase( it );
212  // delete objects
213  FactoryType :: deleteObject( val.first );
214  delete val.second;
215  }
216  };
217 
218  } // namespace Fem
219 
220 } // namespace Dune
221 
222 #endif // #ifndef DUNE_FEM_SINGLETONLIST_HH
Exception thrown when a code segment that is supposed to be only accessed in single thread mode is ac...
Definition: mpimanager.hh:43
Singleton list for key/object pairs.
Definition: singletonlist.hh:53
static void removeObject(const ObjectType &object)
Definition: singletonlist.hh:123
static ListType & singletonList()
Definition: singletonlist.hh:81
static auto getObject(const KeyType &key, Args &&... args) -> std::enable_if_t< std::is_same< decltype(FactoryType::createObject(key, std::forward< Args >(args)...)), ObjectType * >::value, ObjectType & >
Definition: singletonlist.hh:94
static DUNE_EXPORT Object & instance(Args &&... args)
return singleton instance of given Object type.
Definition: singleton.hh:123
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::bool_constant<(sizeof...(II)==0)> empty(std::integer_sequence< T, II... >)
Checks whether the sequence is empty.
Definition: integersequence.hh:80
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 15, 22:30, 2024)