GetFEM++  5.3
dal_static_stored_objects.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2017 Yves Renard
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /** @file dal_static_stored_objects.h
33 @author Yves Renard <Yves.Renard@insa-lyon.fr>
34 @date February 19, 2005
35 @brief Stores interdependent getfem objects.
36 
37 Stored object :
38 
39 A type of object to be stored should derive from
40 dal::static_stored_object and a key should inherit from
41 static_stored_object_key with an overloaded "compare" method.
42 
43 To store a new object, you have to test if the object is not
44 already stored and then call dal::add_stored_object:
45 @code
46 pstatic_stored_object_key p = make_shared<your_object_key>(parameters);
47 if (!search_stored_object(p)) {
48 add_stored_object(p, make_shared<your_object>(parameters));
49 }
50 @endcode
51 You can add a dependency of your new object with
52 @code
53 add_dependency(pointer_on_your_object,
54 pointer_on_the_object_object_from_which_it_depends);
55 @endcode
56 and then your object will be automatically deleted if the second object is
57 deleted.
58 The dependency can be added within the add_stored_object call:
59 @code
60 add_stored_object(new your_object_key(parameters),
61 new your_object(parameters),
62 dependency);
63 @endcode
64 
65 std::shared_ptr are used.
66 */
67 #ifndef DAL_STATIC_STORED_OBJECTS_H__
68 #define DAL_STATIC_STORED_OBJECTS_H__
69 
70 #include "dal_config.h"
71 #include "getfem_omp.h"
72 #include <algorithm>
73 #include "dal_singleton.h"
74 #include <set>
75 #include <list>
76 
77 
78 #include "getfem/getfem_arch_config.h"
79 
80 #ifdef GETFEM_HAVE_OPENMP
81  #include <boost/atomic.hpp>
82  typedef boost::atomic_bool atomic_bool;
83  typedef boost::atomic<int> atomic_int;
84 #else
85  typedef int atomic_int;
86  typedef bool atomic_bool;
87 #endif
88 
89 #define DAL_STORED_OBJECT_DEBUG 0
90 
91 namespace dal {
92 
93 
94 #if DAL_STORED_OBJECT_DEBUG
95 // Little tool for debug : detects the deleted static stored objects for
96 // which the destructor is not called (i.e. a shared pointer is still stored
97 // somewhere. Not thread safe.
98 // Rule : Each potential stored object should called
99 // DAL_STORED_OBJECT_DEBUG_CREATED(this, "name") in the constructor and
100 // DAL_STORED_OBJECT_DEBUG_DESTROYED(this) in the destructor.
101  class static_stored_object;
102  void stored_debug_created(const static_stored_object *o,
103  const std::string &name);
104  void stored_debug_added(const static_stored_object *o);
105  void stored_debug_deleted(const static_stored_object *o);
106  void stored_debug_destroyed(const static_stored_object *o,
107  const std::string &name);
108 # define DAL_STORED_OBJECT_DEBUG_CREATED(o, name) stored_debug_created(o, name)
109 # define DAL_STORED_OBJECT_DEBUG_ADDED(o) stored_debug_added(o)
110 # define DAL_STORED_OBJECT_DEBUG_DELETED(o) stored_debug_deleted(o)
111 # define DAL_STORED_OBJECT_DEBUG_DESTROYED(o, name) \
112  stored_debug_destroyed(o, name)
113 #else
114 # define DAL_STORED_OBJECT_DEBUG_CREATED(o, name)
115 # define DAL_STORED_OBJECT_DEBUG_ADDED(o)
116 # define DAL_STORED_OBJECT_DEBUG_DELETED(o)
117 # define DAL_STORED_OBJECT_DEBUG_DESTROYED(o, name)
118 #endif
119 
120  enum permanence { PERMANENT_STATIC_OBJECT = 0, // not deletable object
121  STRONG_STATIC_OBJECT = 1, // preferable not to delete it
122  STANDARD_STATIC_OBJECT = 2, // standard
123  WEAK_STATIC_OBJECT = 3, // delete it if necessary
124  AUTODELETE_STATIC_OBJECT = 4 // automatically deleted
125  // when the last dependent object is deleted
126  };
127 
128  class static_stored_object_key {
129  protected :
130  virtual bool compare(const static_stored_object_key &) const {
131  GMM_ASSERT1(false, "This method should not be called");
132  }
133 
134  public :
135  bool operator < (const static_stored_object_key &o) const {
136  // comparaison des noms d'objet
137  if (typeid(*this).before(typeid(o))) return true;
138  if (typeid(o).before(typeid(*this))) return false;
139  return compare(o);
140  }
141 
142  virtual ~static_stored_object_key() {}
143 
144  };
145 
146 
147  template <typename var_type>
148  class simple_key : virtual public static_stored_object_key {
149  var_type a;
150  public :
151  virtual bool compare(const static_stored_object_key &oo) const {
152  const simple_key &o = dynamic_cast<const simple_key &>(oo);
153  return (a < o.a);
154  }
155  simple_key(var_type aa) : a(aa) {}
156  };
157 
158 #define DAL_SIMPLE_KEY(class_name, var_type) \
159  struct class_name : public dal::simple_key<var_type> { \
160  class_name(var_type aa) : dal::simple_key<var_type>(aa) {} \
161  }
162 
163 #define DAL_DOUBLE_KEY(class_name, var_type1, var_type2) \
164  struct class_name : \
165  public dal::simple_key<std::pair<var_type1,var_type2> > { \
166  class_name(var_type1 aa, var_type2 bb) : \
167  dal::simple_key<std::pair<var_type1,var_type2> > \
168  (std::make_pair(aa,bb)) {} \
169  }
170 
171 #define DAL_TRIPLE_KEY(class_name, var_type1, var_type2, var_type3) \
172  struct class_name : \
173  public dal::simple_key<std::pair<var_type1, \
174  std::pair<var_type2,var_type3> > > { \
175  class_name(var_type1 aa, var_type2 bb, var_type3 cc) : \
176  dal::simple_key<std::pair<var_type1, \
177  std::pair<var_type2, var_type3> > > \
178  (std::make_pair(aa,std::make_pair(bb,cc))) {} \
179  }
180 
181 #define DAL_FOUR_KEY(class_name,var_type1,var_type2,var_type3,var_type4)\
182  struct class_name : public \
183  dal::simple_key<std::pair \
184  <var_type1, std::pair<var_type2, std::pair \
185  <var_type3,var_type4> > > > { \
186  class_name(var_type1 aa, var_type2 bb, var_type3 cc,var_type4 dd) : \
187  dal::simple_key<std::pair \
188  <var_type1, std::pair<var_type2, \
189  std::pair<var_type3, \
190  var_type4> > > > \
191  (std::make_pair(aa,std::make_pair(bb,std::make_pair(cc, dd)))) {} \
192  }
193 
194 
195  typedef std::shared_ptr<const static_stored_object_key>
196  pstatic_stored_object_key;
197 
198 
199  /**
200  base class for static stored objects
201  */
202  class static_stored_object { public : virtual ~static_stored_object() {} };
203 
204  typedef std::shared_ptr<const static_stored_object> pstatic_stored_object;
205 
206  pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o);
207 
208  /** Gives a pointer to an object from a key pointer. */
209  pstatic_stored_object search_stored_object(pstatic_stored_object_key k);
210 
211  /** Test if an object is stored*/
212  bool exists_stored_object(pstatic_stored_object o);
213 
214  /** Add a dependency, object o1 will depend on object o2. */
215  void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2);
216 
217  /** remove a dependency. Return true if o2 has no more dependent object. */
218  bool del_dependency(pstatic_stored_object o1, pstatic_stored_object o2);
219 
220  /** Add an object with two optional dependencies. */
221  void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
222  permanence perm = STANDARD_STATIC_OBJECT);
223 
224  inline void
225  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
226  pstatic_stored_object dep1,
227  permanence perm = STANDARD_STATIC_OBJECT) {
228  add_stored_object(k, o, perm);
229  add_dependency(o, dep1);
230  }
231 
232  inline void
233  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
234  pstatic_stored_object dep1, pstatic_stored_object dep2,
235  permanence perm = STANDARD_STATIC_OBJECT) {
236  add_stored_object(k, o, perm);
237  add_dependency(o, dep1);
238  add_dependency(o, dep2);
239  }
240 
241  inline void
242  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
243  pstatic_stored_object dep1, pstatic_stored_object dep2,
244  pstatic_stored_object dep3,
245  permanence perm = STANDARD_STATIC_OBJECT) {
246  add_stored_object(k, o, perm);
247  add_dependency(o, dep1);
248  add_dependency(o, dep2);
249  add_dependency(o, dep3);
250  }
251 
252  inline void
253  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
254  pstatic_stored_object dep1, pstatic_stored_object dep2,
255  pstatic_stored_object dep3, pstatic_stored_object dep4,
256  permanence perm = STANDARD_STATIC_OBJECT) {
257  add_stored_object(k, o, perm);
258  add_dependency(o, dep1);
259  add_dependency(o, dep2);
260  add_dependency(o, dep3);
261  add_dependency(o, dep4);
262  }
263 
264  /** Delete an object and the object which depend on it. */
265  void del_stored_object(const pstatic_stored_object &o,
266  bool ignore_unstored=false);
267 
268  /** Delete all the object whose permanence is greater or equal to perm. */
269  void del_stored_objects(int perm);
270 
271  /** Show a list of stored objects (for debugging purpose). */
272  void list_stored_objects(std::ostream &ost);
273 
274  /** Return the number of stored objects (for debugging purpose). */
275  size_t nb_stored_objects(void);
276 
277  /** Delete a list of objects and their dependencies*/
278  void del_stored_objects(std::list<pstatic_stored_object> &to_delete,
279  bool ignore_unstored);
280 
281  /** Test the validity of the whole global storage */
282  void test_stored_objects(void);
283 
284 
285  /** Pointer to an object with the dependencies */
287  pstatic_stored_object p;
288  atomic_bool valid;
289  const permanence perm;
290  std::set<pstatic_stored_object> dependent_object;
291  std::set<pstatic_stored_object> dependencies;
292  enr_static_stored_object(pstatic_stored_object o, permanence perma)
293  : p(o), perm(perma) {valid = true;}
295  : perm(STANDARD_STATIC_OBJECT) {valid = true;}
297  : p(enr_o.p), perm(enr_o.perm), dependent_object(enr_o.dependent_object),
298  dependencies(enr_o.dependencies){valid = static_cast<bool>(enr_o.perm);}
299  };
300 
301 
302 
303  /** Pointer to a key with a coherent order */
305  pstatic_stored_object_key p;
306  bool operator < (const enr_static_stored_object_key &o) const
307  { return (*p) < (*(o.p)); }
308  enr_static_stored_object_key(pstatic_stored_object_key o) : p(o) {}
309  };
310 
311 
312 
313  /** Table of stored objects. Thread safe, uses thread specific mutexes. */
315  public std::map<enr_static_stored_object_key, enr_static_stored_object> {
316 
317  typedef std::map<pstatic_stored_object,pstatic_stored_object_key>
318  stored_key_tab;
319 
322  pstatic_stored_object
323  search_stored_object(pstatic_stored_object_key k) const;
324  bool has_dependent_objects(pstatic_stored_object o) const;
325  bool exists_stored_object(pstatic_stored_object o) const;
326  //adding the object to the storage on the current thread
327  void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
328  permanence perm);
329 
330  iterator iterator_of_object_(pstatic_stored_object o);
331  //delete o2 from the dependency list of o1
332  //true if successfull, false if o1 is not
333  //on this thread
334  bool del_dependency_(pstatic_stored_object o1,
335  pstatic_stored_object o2);
336  //delete o1 from the dependent list of o2
337  //true if successfull, false if o1 is not
338  //on this thread
339  bool del_dependent_(pstatic_stored_object o1,
340  pstatic_stored_object o2);
341  //add o2 to the dependency list of o1
342  //true if successfull, false if o1 is not
343  //on this thread
344  bool add_dependency_(pstatic_stored_object o1,
345  pstatic_stored_object o2);
346  //add o1 to the dependent list of o2
347  //true if successfull, false if o1 is not
348  //on this thread
349  bool add_dependent_(pstatic_stored_object o1,
350  pstatic_stored_object o2);
351  void basic_delete_(std::list<pstatic_stored_object> &to_delete);
352 
353  getfem::lock_factory locks_;
354  stored_key_tab stored_keys_;
355  };
356 
357 
358 
359  /** delete all the specific type of stored objects*/
360  template<typename OBJECT_TYPE>
361  void delete_specific_type_stored_objects(bool all_thread = false)
362  {
363  typedef typename stored_object_tab::iterator iterator;
364  std::list<pstatic_stored_object> delete_object_list;
365 
366  if(!all_thread){
367  stored_object_tab& stored_objects
369 
370  iterator itb = stored_objects.begin();
371  iterator ite = stored_objects.end();
372 
373  for(iterator it = itb; it != ite; ++it){
374  const OBJECT_TYPE *p_object
375  = std::dynamic_pointer_cast<const OBJECT_TYPE>(it->second.p).get();
376  if(p_object != 0) delete_object_list.push_back(it->second.p);
377  }
378  }
379  else{
380  for(size_t thread = 0; thread<getfem::num_threads();thread++)
381  {
382  stored_object_tab& stored_objects
384 
385  iterator itb = stored_objects.begin();
386  iterator ite = stored_objects.end();
387 
388  for(iterator it = itb; it != ite; ++it){
389  const OBJECT_TYPE *p_object
390  = std::dynamic_pointer_cast<const OBJECT_TYPE>(it->second.p).get();
391  if(p_object != 0) delete_object_list.push_back(it->second.p);
392  }
393  }
394  }
395  del_stored_objects(delete_object_list, false);
396  }
397 }
398 
399 #endif /* DAL_STATIC_STORED_OBJECTS_H__ */
Pointer to a key with a coherent order.
void test_stored_objects(void)
Test the validity of the whole global storage.
base class for static stored objects
void list_stored_objects(std::ostream &ost)
Show a list of stored objects (for debugging purpose).
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
Tools for multithreaded, OpenMP and Boost based parallelization.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
static T & instance()
Instance from the current thread.
defines and typedefs for namespace dal
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
A simple singleton implementation.
bool del_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
remove a dependency.
Table of stored objects.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
Dynamic Array Library.
void del_stored_objects(std::list< pstatic_stored_object > &to_delete, bool ignore_unstored)
Delete a list of objects and their dependencies.
Pointer to an object with the dependencies.
bool exists_stored_object(pstatic_stored_object o)
Test if an object is stored.
size_t nb_stored_objects(void)
Return the number of stored objects (for debugging purpose).
void delete_specific_type_stored_objects(bool all_thread=false)
delete all the specific type of stored objects