GetFEM  5.4.2
dal_static_stored_objects.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2020 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 #include <atomic>
81 
82 #define DAL_STORED_OBJECT_DEBUG 0
83 
84 namespace dal {
85 
86 
87 #if DAL_STORED_OBJECT_DEBUG
88 // Little tool for debug : detects the deleted static stored objects for
89 // which the destructor is not called (i.e. a shared pointer is still stored
90 // somewhere. Not thread safe.
91 // Rule : Each potential stored object should called
92 // DAL_STORED_OBJECT_DEBUG_CREATED(this, "name") in the constructor and
93 // DAL_STORED_OBJECT_DEBUG_DESTROYED(this) in the destructor.
94  class static_stored_object;
95  void stored_debug_created(const static_stored_object *o,
96  const std::string &name);
97  void stored_debug_added(const static_stored_object *o);
98  void stored_debug_deleted(const static_stored_object *o);
99  void stored_debug_destroyed(const static_stored_object *o,
100  const std::string &name);
101 # define DAL_STORED_OBJECT_DEBUG_CREATED(o, name) stored_debug_created(o, name)
102 # define DAL_STORED_OBJECT_DEBUG_ADDED(o) stored_debug_added(o)
103 # define DAL_STORED_OBJECT_DEBUG_DELETED(o) stored_debug_deleted(o)
104 # define DAL_STORED_OBJECT_DEBUG_DESTROYED(o, name) \
105  stored_debug_destroyed(o, name)
106 #else
107 # define DAL_STORED_OBJECT_DEBUG_CREATED(o, name)
108 # define DAL_STORED_OBJECT_DEBUG_ADDED(o)
109 # define DAL_STORED_OBJECT_DEBUG_DELETED(o)
110 # define DAL_STORED_OBJECT_DEBUG_DESTROYED(o, name)
111 #endif
112 
113  enum permanence { PERMANENT_STATIC_OBJECT = 0, // not deletable object
114  STRONG_STATIC_OBJECT = 1, // preferable not to delete it
115  STANDARD_STATIC_OBJECT = 2, // standard
116  WEAK_STATIC_OBJECT = 3, // delete it if necessary
117  AUTODELETE_STATIC_OBJECT = 4 // automatically deleted
118  // when the last dependent object is deleted
119  };
120 
121  class static_stored_object_key {
122  protected :
123  virtual bool compare(const static_stored_object_key &) const = 0;
124  virtual bool equal(const static_stored_object_key &) const = 0;
125 
126  public :
127  bool operator < (const static_stored_object_key &o) const {
128  // comparaison des noms d'objet
129  if (typeid(*this).before(typeid(o))) return true;
130  if (typeid(o).before(typeid(*this))) return false;
131  return compare(o);
132  }
133 
134  bool operator == (const static_stored_object_key &o) const {
135  if (typeid(o)!=typeid(*this)) return false;
136  return equal(o);
137  }
138 
139  bool operator != (const static_stored_object_key &o) const {
140  return !(*this == o);
141  }
142 
143  virtual ~static_stored_object_key() {}
144  };
145 
146  template <typename var_type>
147  class simple_key : virtual public static_stored_object_key {
148  var_type a;
149  public :
150  bool compare(const static_stored_object_key &oo) const override {
151  auto &o = dynamic_cast<const simple_key &>(oo);
152  return a < o.a;
153  }
154 
155  bool equal(const static_stored_object_key &oo) const override {
156  auto &o = dynamic_cast<const simple_key &>(oo);
157  return a == o.a;
158  }
159  simple_key(var_type aa) : a(aa) {}
160  };
161 
162 #define DAL_SIMPLE_KEY(class_name, var_type) \
163  struct class_name : public dal::simple_key<var_type> { \
164  class_name(var_type aa) : dal::simple_key<var_type>(aa) {} \
165  }
166 
167 #define DAL_DOUBLE_KEY(class_name, var_type1, var_type2) \
168  struct class_name : \
169  public dal::simple_key<std::pair<var_type1,var_type2> > { \
170  class_name(var_type1 aa, var_type2 bb) : \
171  dal::simple_key<std::pair<var_type1,var_type2> > \
172  (std::make_pair(aa,bb)) {} \
173  }
174 
175 #define DAL_TRIPLE_KEY(class_name, var_type1, var_type2, var_type3) \
176  struct class_name : \
177  public dal::simple_key<std::pair<var_type1, \
178  std::pair<var_type2,var_type3> > > { \
179  class_name(var_type1 aa, var_type2 bb, var_type3 cc) : \
180  dal::simple_key<std::pair<var_type1, \
181  std::pair<var_type2, var_type3> > > \
182  (std::make_pair(aa,std::make_pair(bb,cc))) {} \
183  }
184 
185 #define DAL_FOUR_KEY(class_name,var_type1,var_type2,var_type3,var_type4)\
186  struct class_name : public \
187  dal::simple_key<std::pair \
188  <var_type1, std::pair<var_type2, std::pair \
189  <var_type3,var_type4> > > > { \
190  class_name(var_type1 aa, var_type2 bb, var_type3 cc,var_type4 dd) : \
191  dal::simple_key<std::pair \
192  <var_type1, std::pair<var_type2, \
193  std::pair<var_type3, \
194  var_type4> > > > \
195  (std::make_pair(aa,std::make_pair(bb,std::make_pair(cc, dd)))) {} \
196  }
197 
198 
199  typedef std::shared_ptr<const static_stored_object_key>
200  pstatic_stored_object_key;
201 
202 
203  /**
204  base class for static stored objects
205  */
206  class static_stored_object { public : virtual ~static_stored_object() {} };
207 
208  typedef std::shared_ptr<const static_stored_object> pstatic_stored_object;
209 
210  pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o);
211 
212  /** Gives a pointer to an object from a key pointer. */
213  pstatic_stored_object search_stored_object(pstatic_stored_object_key k);
214 
215  pstatic_stored_object search_stored_object_on_all_threads(pstatic_stored_object_key k);
216 
217  /** Test if an object is stored*/
218  bool exists_stored_object(pstatic_stored_object o);
219 
220  /** Add a dependency, object o1 will depend on object o2. */
221  void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2);
222 
223  /** remove a dependency. Return true if o2 has no more dependent object. */
224  bool del_dependency(pstatic_stored_object o1, pstatic_stored_object o2);
225 
226  /** Add an object with two optional dependencies. */
227  void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
228  permanence perm = STANDARD_STATIC_OBJECT);
229 
230  inline void
231  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
232  pstatic_stored_object dep1,
233  permanence perm = STANDARD_STATIC_OBJECT) {
234  add_stored_object(k, o, perm);
235  add_dependency(o, dep1);
236  }
237 
238  inline void
239  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
240  pstatic_stored_object dep1, pstatic_stored_object dep2,
241  permanence perm = STANDARD_STATIC_OBJECT) {
242  add_stored_object(k, o, perm);
243  add_dependency(o, dep1);
244  add_dependency(o, dep2);
245  }
246 
247  inline void
248  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
249  pstatic_stored_object dep1, pstatic_stored_object dep2,
250  pstatic_stored_object dep3,
251  permanence perm = STANDARD_STATIC_OBJECT) {
252  add_stored_object(k, o, perm);
253  add_dependency(o, dep1);
254  add_dependency(o, dep2);
255  add_dependency(o, dep3);
256  }
257 
258  inline void
259  add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
260  pstatic_stored_object dep1, pstatic_stored_object dep2,
261  pstatic_stored_object dep3, pstatic_stored_object dep4,
262  permanence perm = STANDARD_STATIC_OBJECT) {
263  add_stored_object(k, o, perm);
264  add_dependency(o, dep1);
265  add_dependency(o, dep2);
266  add_dependency(o, dep3);
267  add_dependency(o, dep4);
268  }
269 
270  /** Delete an object and the object which depend on it. */
271  void del_stored_object(const pstatic_stored_object &o,
272  bool ignore_unstored=false);
273 
274  /** Delete all the object whose permanence is greater or equal to perm. */
275  void del_stored_objects(int perm);
276 
277  /** Show a list of stored objects (for debugging purpose). */
278  void list_stored_objects(std::ostream &ost);
279 
280  /** Return the number of stored objects (for debugging purpose). */
281  size_t nb_stored_objects(void);
282 
283  /** Delete a list of objects and their dependencies*/
284  void del_stored_objects(std::list<pstatic_stored_object> &to_delete,
285  bool ignore_unstored);
286 
287  /** Test the validity of the whole global storage */
288  void test_stored_objects(void);
289 
290 
291  /** Pointer to an object with the dependencies */
293  pstatic_stored_object p;
294  std::atomic_bool valid;
295  const permanence perm;
296  std::set<pstatic_stored_object> dependent_object;
297  std::set<pstatic_stored_object> dependencies;
298  enr_static_stored_object(pstatic_stored_object o, permanence perma)
299  : p(o), perm(perma) {valid = true;}
301  : perm(STANDARD_STATIC_OBJECT) {valid = true;}
303  : p(enr_o.p), perm(enr_o.perm), dependent_object(enr_o.dependent_object),
304  dependencies(enr_o.dependencies){valid = static_cast<bool>(enr_o.perm);}
305  };
306 
307 
308 
309  /** Pointer to a key with a coherent order */
311  pstatic_stored_object_key p;
312  bool operator < (const enr_static_stored_object_key &o) const
313  { return (*p) < (*(o.p)); }
314  enr_static_stored_object_key(pstatic_stored_object_key o) : p(o) {}
315  };
316 
317 
318 
319  /** Table of stored objects. Thread safe, uses thread specific mutexes. */
321  public std::map<enr_static_stored_object_key, enr_static_stored_object> {
322 
323  typedef std::map<pstatic_stored_object,pstatic_stored_object_key>
324  stored_key_tab;
325 
328  pstatic_stored_object
329  search_stored_object(pstatic_stored_object_key k) const;
330  bool has_dependent_objects(pstatic_stored_object o) const;
331  bool exists_stored_object(pstatic_stored_object o) const;
332  //adding the object to the storage on the current thread
333  void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o,
334  permanence perm);
335 
336  iterator iterator_of_object_(pstatic_stored_object o);
337  //delete o2 from the dependency list of o1
338  //true if successfull, false if o1 is not
339  //on this thread
340  bool del_dependency_(pstatic_stored_object o1,
341  pstatic_stored_object o2);
342  //delete o1 from the dependent list of o2
343  //true if successfull, false if o1 is not
344  //on this thread
345  bool del_dependent_(pstatic_stored_object o1,
346  pstatic_stored_object o2);
347  //add o2 to the dependency list of o1
348  //true if successfull, false if o1 is not
349  //on this thread
350  bool add_dependency_(pstatic_stored_object o1,
351  pstatic_stored_object o2);
352  //add o1 to the dependent list of o2
353  //true if successfull, false if o1 is not
354  //on this thread
355  bool add_dependent_(pstatic_stored_object o1,
356  pstatic_stored_object o2);
357  void basic_delete_(std::list<pstatic_stored_object> &to_delete);
358 
359  getfem::lock_factory locks_;
360  stored_key_tab stored_keys_;
361  };
362 
363 
364 
365  /** delete all the specific type of stored objects*/
366  template<typename OBJECT_TYPE>
367  void delete_specific_type_stored_objects(bool all_threads = false){
368  std::list<pstatic_stored_object> delete_object_list;
369 
370  auto filter_objects = [&](stored_object_tab &stored_objects){
371  for(auto &&pair : stored_objects){
372  auto p_object = std::dynamic_pointer_cast<const OBJECT_TYPE>(pair.second.p);
373  if(p_object != nullptr) delete_object_list.push_back(pair.second.p);
374  }
375  };
376 
377  if (!all_threads){
378  auto& stored_objects = singleton<stored_object_tab>::instance();
379  filter_objects(stored_objects);
380  }
381  else{
382  for(size_t thread = 0; thread < singleton<stored_object_tab>::num_threads(); ++thread)
383  {
384  auto& stored_objects = singleton<stored_object_tab>::instance(thread);
385  filter_objects(stored_objects);
386  }
387  }
388  del_stored_objects(delete_object_list, false);
389  }
390 }
391 
392 #endif /* DAL_STATIC_STORED_OBJECTS_H__ */
dal::singleton::instance
static T & instance()
Instance from the current thread.
Definition: dal_singleton.h:165
dal::enr_static_stored_object_key
Pointer to a key with a coherent order.
Definition: dal_static_stored_objects.h:310
dal_singleton.h
A simple singleton implementation.
dal
Dynamic Array Library.
Definition: dal_backtrace.cc:29
dal::del_stored_object
void del_stored_object(const pstatic_stored_object &o, bool ignore_unstored)
Delete an object and the object which depend on it.
Definition: dal_static_stored_objects.cc:369
dal::del_dependency
bool del_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
remove a dependency.
Definition: dal_static_stored_objects.cc:256
dal::delete_specific_type_stored_objects
void delete_specific_type_stored_objects(bool all_threads=false)
delete all the specific type of stored objects
Definition: dal_static_stored_objects.h:367
dal::enr_static_stored_object
Pointer to an object with the dependencies.
Definition: dal_static_stored_objects.h:292
dal::stored_object_tab::stored_object_tab
stored_object_tab()
STATIC_STORED_TAB ----------------------------------------------------—.
Definition: dal_static_stored_objects.cc:415
dal::search_stored_object
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
Definition: dal_static_stored_objects.cc:177
dal_config.h
defines and typedefs for namespace dal
dal::nb_stored_objects
size_t nb_stored_objects(void)
Return the number of stored objects (for debugging purpose).
Definition: dal_static_stored_objects.cc:402
getfem_omp.h
Tools for multithreaded, OpenMP and Boost based parallelization.
dal::stored_object_tab
Table of stored objects.
Definition: dal_static_stored_objects.h:320
dal::list_stored_objects
void list_stored_objects(std::ostream &ost)
Show a list of stored objects (for debugging purpose).
Definition: dal_static_stored_objects.cc:389
dal::exists_stored_object
bool exists_stored_object(pstatic_stored_object o)
Test if an object is stored.
Definition: dal_static_stored_objects.cc:171
dal::add_stored_object
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
Definition: dal_static_stored_objects.cc:284
dal::static_stored_object
base class for static stored objects
Definition: dal_static_stored_objects.h:206
dal::del_stored_objects
void del_stored_objects(std::list< pstatic_stored_object > &to_delete, bool ignore_unstored)
Delete a list of objects and their dependencies.
Definition: dal_static_stored_objects.cc:311
dal::test_stored_objects
void test_stored_objects(void)
Test the validity of the whole global storage.
Definition: dal_static_stored_objects.cc:211
dal::add_dependency
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
Definition: dal_static_stored_objects.cc:230