35 #define DAL_STORED_OBJECT_DEBUG_NOISY 2
37 #if DAL_STORED_OBJECT_DEBUG
39 static bool dal_static_stored_tab_valid__ =
true;
41 #define STORED_ASSERT(test, message) GMM_ASSERT1(test, message);
42 #define ON_STORED_DEBUG(expression) expression;
44 static std::map <const static_stored_object *, std::string> _created_objects;
45 static std::map <const static_stored_object *, std::string> _added_objects;
46 static std::map <const static_stored_object *, std::string> _deleted_objects;
49 void stored_debug_created(
const static_stored_object *o,
50 const std::string &name) {
51 if (dal_static_stored_tab_valid__) {
52 _created_objects[o] = name;
53 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
54 cout <<
"Created " << name <<
" : " << o << endl;
58 void stored_debug_added(
const static_stored_object *o) {
59 if (dal_static_stored_tab_valid__) {
60 auto it = _created_objects.find(o);
61 if (it == _created_objects.end()) {
62 _added_objects[o] =
"";
63 # if DAL_STORED_OBJECT_DEBUG_NOISY > 0
64 cout <<
"Adding an unknown object " << o <<
" of type "
65 <<
typeid(*o).name() <<
" add DAL_STORED_OBJECT_DEBUG_CREATED"
66 "(o, name) in its constructor" << endl;
69 _added_objects[o] = it->second;
70 _created_objects.erase(it);
71 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
72 cout <<
"Added " << it->second <<
" : " << o << endl;
75 if (_deleted_objects.size()) {
76 cout << endl <<
"Number of stored objects: " << _added_objects.size()
77 << endl <<
"Number of unstored created objects: "
78 << _created_objects.size() << endl
79 <<
"Number of undestroyed object: "
80 << _deleted_objects.size() << endl;
81 for (
auto &x : _deleted_objects)
82 cout <<
"UNDESTROYED OBJECT " << x.second <<
" : " << x.first << endl;
87 void stored_debug_deleted(
const static_stored_object *o) {
88 if (dal_static_stored_tab_valid__) {
89 auto it = _added_objects.find(o);
90 if (it == _added_objects.end()) {
91 cout <<
"Deleting an unknown object ! " << o << endl;
92 _deleted_objects[o] =
"";
94 _deleted_objects[o] = it->second;
95 _added_objects.erase(it);
96 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
97 cout <<
"Deleted " << it->second <<
" : " << o << endl;
103 void stored_debug_destroyed(
const static_stored_object *o,
104 const std::string &name) {
105 if (dal_static_stored_tab_valid__) {
106 auto it = _deleted_objects.find(o);
107 if (it == _deleted_objects.end()) {
108 it = _created_objects.find(o);
109 if (it == _created_objects.end()) {
110 it = _added_objects.find(o);
111 if (it == _added_objects.end()) {
112 cout <<
"Destroy an unknown object ! " << o <<
" name given : "
115 _added_objects.erase(it);
116 cout <<
"Destroy a non deleted object !! " << o <<
" name given : "
120 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
121 cout <<
"Destroy an unadded object " << it->second <<
" : "
124 _created_objects.erase(it);
127 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
128 cout <<
"Destroy " << it->second <<
" : " << o <<
" name given : "
131 _deleted_objects.erase(it);
138 #define STORED_ASSERT(test, message)
139 #define ON_STORED_DEBUG(expression)
144 pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o,
size_t thread){
146 STORED_ASSERT(dal_static_stored_tab_valid__,
"Too late to do that");
147 auto it = stored_keys.find(o);
148 if (it != stored_keys.end())
return it->second;
153 pstatic_stored_object_key key_of_stored_object_other_threads(pstatic_stored_object o){
157 auto key = key_of_stored_object(o,thread);
163 pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o){
167 key_of_stored_object_other_threads(o) : nullptr;
173 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return false)
174 return (stored_keys.find(o) != stored_keys.end());
179 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return nullptr)
180 return stored_objects.search_stored_object(k);
183 pstatic_stored_object search_stored_object_on_all_threads(pstatic_stored_object_key k){
185 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return nullptr)
186 auto p = stored_objects.search_stored_object(k);
189 for(
size_t thread = 0; thread < singleton<stored_object_tab>::num_threads(); ++thread){
192 p = other_objects.search_stored_object(k);
198 std::pair<stored_object_tab::iterator, stored_object_tab::iterator>
199 iterators_of_object(pstatic_stored_object o){
202 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
203 auto it = stored_objects.iterator_of_object_(o);
204 if (it != stored_objects.end())
return {it, stored_objects.end()};
214 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
215 auto& stored_keys = stored_objects.stored_keys_;
217 GMM_ASSERT1(stored_objects.size() == stored_keys.size(),
218 "keys and objects tables don't match");
219 for (
auto &&pair : stored_keys){
220 auto itos = iterators_of_object(pair.first);
221 GMM_ASSERT1(itos.first != itos.second,
"Key without object is found");
223 for (
auto &&pair : stored_objects){
224 auto itos = iterators_of_object(pair.second.p);
225 GMM_ASSERT1(itos.first != itos.second,
"Object has key but cannot be found");
231 pstatic_stored_object o2) {
232 bool dep_added =
false;
235 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return)
236 if ((dep_added = stored_objects.add_dependency_(o1,o2)))
break;
238 GMM_ASSERT1(dep_added,
"Failed to add dependency between " << o1
239 <<
" of type " <<
typeid(*o1).name() <<
" and " << o2
240 <<
" of type " <<
typeid(*o2).name() <<
". ");
242 bool dependent_added =
false;
245 if ((dependent_added = stored_objects.add_dependent_(o1,o2)))
break;
247 GMM_ASSERT1(dependent_added,
"Failed to add dependent between " << o1
248 <<
" of type " <<
typeid(*o1).name() <<
" and " << o2
249 <<
" of type " <<
typeid(*o2).name() <<
". ");
257 bool dep_deleted =
false;
260 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return false)
261 if ((dep_deleted = stored_objects.del_dependency_(o1,o2)))
break;
263 GMM_ASSERT1(dep_deleted,
"Failed to delete dependency between " << o1 <<
" of type "
264 <<
typeid(*o1).name() <<
" and " << o2 <<
" of type "
265 <<
typeid(*o2).name() <<
". ");
267 bool dependent_deleted =
false;
268 bool dependent_empty =
false;
271 dependent_deleted = stored_objects.del_dependent_(o1,o2);
272 if (dependent_deleted){
273 dependent_empty = stored_objects.has_dependent_objects(o2);
277 GMM_ASSERT1(dependent_deleted,
"Failed to delete dependent between " << o1 <<
" of type "
278 <<
typeid(*o1).name() <<
" and " << o2 <<
" of type "
279 <<
typeid(*o2).name() <<
". ");
281 return dependent_empty;
286 STORED_ASSERT(dal_static_stored_tab_valid__,
"Too late to add an object");
288 stored_objects.add_stored_object(k,o,perm);
291 void basic_delete(std::list<pstatic_stored_object> &to_delete){
294 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return)
295 stored_objects_this_thread.basic_delete_(to_delete);
297 if (!to_delete.empty()){
301 stored_objects.basic_delete_(to_delete);
302 if (to_delete.empty())
break;
306 if (!to_delete.empty()) GMM_WARNING1(
"Not all objects were deleted");
308 else{GMM_ASSERT1(to_delete.empty(),
"Could not delete objects");}
312 bool ignore_unstored) {
316 ON_STORED_DEBUG(
if (dal_static_stored_tab_valid__)
return);
318 std::list<pstatic_stored_object>::iterator it, itnext;
319 for (it = to_delete.begin(); it != to_delete.end(); it = itnext) {
320 itnext = it; itnext++;
322 auto itos = iterators_of_object(*it);
323 if (itos.first == itos.second) {
324 if (ignore_unstored) to_delete.erase(it);
326 GMM_WARNING1(
"This object is (already?) not stored : "<< it->get()
327 <<
" typename: " <<
typeid(*it->get()).name()
328 <<
"(which could happen in multithreaded code and is OK)");
330 GMM_ASSERT1(
false,
"This object is not stored : " << it->get()
331 <<
" typename: " <<
typeid(*it->get()).name());
334 else itos.first->second.valid =
false;
337 for (
auto &&pobj : to_delete) {
339 auto itos = iterators_of_object(pobj);
340 GMM_ASSERT1(itos.first != itos.second,
"An object disapeared !");
341 itos.first->second.valid =
false;
342 auto second_dep = itos.first->second.dependencies;
343 for (
const auto &pdep : second_dep) {
345 auto itods = iterators_of_object(pdep);
346 if (itods.first->second.perm == AUTODELETE_STATIC_OBJECT
347 && itods.first->second.valid) {
348 itods.first->second.valid =
false;
349 to_delete.push_back(pdep);
353 for (
auto &&pdep : itos.first->second.dependent_object) {
354 auto itods = iterators_of_object(pdep);
355 if (itods.first != itods.second) {
356 GMM_ASSERT1(itods.first->second.perm != PERMANENT_STATIC_OBJECT,
357 "Trying to delete a permanent object " << pdep);
358 if (itods.first->second.valid) {
359 itods.first->second.valid =
false;
360 to_delete.push_back(itods.first->second.p);
366 basic_delete(to_delete);
370 std::list<pstatic_stored_object> to_delete;
371 to_delete.push_back(o);
377 std::list<pstatic_stored_object> to_delete;
380 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
381 if (perm == PERMANENT_STATIC_OBJECT) perm = STRONG_STATIC_OBJECT;
382 for (
auto &&pair : stored_objects){
383 if (pair.second.perm >= perm) to_delete.push_back(pair.second.p);
392 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
393 if (stored_keys.begin() == stored_keys.end())
394 ost <<
"No static stored objects" << endl;
395 else ost <<
"Static stored objects" << endl;
396 for (
const auto &t : stored_keys)
397 ost <<
"Object: " << t.first <<
" typename: "
398 <<
typeid(*(t.first)).name() << endl;
403 long num_objects = 0;
406 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
407 num_objects += stored_keys.size();
417 locks_{}, stored_keys_{}{
418 ON_STORED_DEBUG(dal_static_stored_tab_valid__ =
true;)
421 stored_object_tab::~stored_object_tab(){
422 ON_STORED_DEBUG(dal_static_stored_tab_valid__ =
false;)
425 pstatic_stored_object
426 stored_object_tab::search_stored_object(pstatic_stored_object_key k)
const{
427 auto guard = locks_.get_lock();
428 auto it = find(enr_static_stored_object_key(k));
429 return (it != end()) ? it->second.p :
nullptr;
432 bool stored_object_tab::add_dependency_(pstatic_stored_object o1,
433 pstatic_stored_object o2){
434 auto guard = locks_.get_lock();
435 auto it = stored_keys_.find(o1);
436 if (it == stored_keys_.end())
return false;
437 auto ito1 = find(it->second);
438 GMM_ASSERT1(ito1 != end(),
"Object has a key, but cannot be found");
439 ito1->second.dependencies.insert(o2);
443 void stored_object_tab::add_stored_object(pstatic_stored_object_key k,
444 pstatic_stored_object o, permanence perm){
445 DAL_STORED_OBJECT_DEBUG_ADDED(o.get());
446 auto guard = locks_.get_lock();
447 GMM_ASSERT1(stored_keys_.find(o) == stored_keys_.end(),
448 "This object has already been stored, possibly with another key");
450 insert(std::make_pair(enr_static_stored_object_key(k),
451 enr_static_stored_object(o, perm)));
453 GMM_ASSERT2(stored_keys_.size() == size() && t !=
size_t(-1),
454 "stored_keys are not consistent with stored_object tab");
457 bool stored_object_tab::add_dependent_(pstatic_stored_object o1,
458 pstatic_stored_object o2){
459 auto guard = locks_.get_lock();
460 auto it = stored_keys_.find(o2);
461 if (it == stored_keys_.end())
return false;
462 auto ito2 = find(it->second);
463 GMM_ASSERT1(ito2 != end(),
"Object has a key, but cannot be found");
464 ito2->second.dependent_object.insert(o1);
468 bool stored_object_tab::del_dependency_(pstatic_stored_object o1,
469 pstatic_stored_object o2){
470 auto guard = locks_.get_lock();
471 auto it1 = stored_keys_.find(o1);
472 if (it1 == stored_keys_.end())
return false;
473 auto ito1 = find(it1->second);
474 GMM_ASSERT1(ito1 != end(),
"Object has a key, but cannot be found");
475 ito1->second.dependencies.erase(o2);
479 stored_object_tab::iterator stored_object_tab
480 ::iterator_of_object_(pstatic_stored_object o){
481 auto itk = stored_keys_.find(o);
482 if (itk == stored_keys_.end())
return end();
483 auto ito = find(itk->second);
484 GMM_ASSERT1(ito != end(),
"Object has a key, but is not stored");
488 bool stored_object_tab::del_dependent_(pstatic_stored_object o1,
489 pstatic_stored_object o2){
490 auto guard = locks_.get_lock();
491 auto it2 = stored_keys_.find(o2);
492 if (it2 == stored_keys_.end())
return false;
493 auto ito2 = find(it2->second);
494 GMM_ASSERT1(ito2 != end(),
"Object has a key, but cannot be found");
495 ito2->second.dependent_object.erase(o1);
499 bool stored_object_tab::exists_stored_object(pstatic_stored_object o)
const{
500 auto guard = locks_.get_lock();
501 return (stored_keys_.find(o) != stored_keys_.end());
504 bool stored_object_tab::has_dependent_objects(pstatic_stored_object o)
const{
505 auto guard = locks_.get_lock();
506 auto it = stored_keys_.find(o);
507 GMM_ASSERT1(it != stored_keys_.end(),
"Object is not stored");
508 auto ito = find(it->second);
509 GMM_ASSERT1(ito != end(),
"Object has a key, but cannot be found");
510 return ito->second.dependent_object.empty();
513 void stored_object_tab::basic_delete_(std::list<pstatic_stored_object> &to_delete){
514 auto guard = locks_.get_lock();
515 for (
auto it = to_delete.begin(); it != to_delete.end();){
516 DAL_STORED_OBJECT_DEBUG_DELETED(it->get());
517 auto itk = stored_keys_.find(*it);
519 if (itk != stored_keys_.end()){
520 ito = find(itk->second);
521 stored_keys_.erase(itk);
525 it = to_delete.erase(it);
static size_type this_thread()
this thread number according to the threading policy of the singleton
static T & instance()
Instance from the current thread.
static size_type num_threads()
number of threads this singleton is distributed on.
A simple singleton implementation.
Stores interdependent getfem objects.
void del_stored_objects(std::list< pstatic_stored_object > &to_delete, bool ignore_unstored)
Delete a list of objects and their dependencies.
void add_stored_object(pstatic_stored_object_key k, pstatic_stored_object o, permanence perm)
Add an object with two optional dependencies.
void test_stored_objects(void)
Test the validity of the whole global storage.
void add_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
Add a dependency, object o1 will depend on object o2.
bool del_dependency(pstatic_stored_object o1, pstatic_stored_object o2)
remove a dependency.
size_t nb_stored_objects(void)
Return the number of stored objects (for debugging purpose).
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.
pstatic_stored_object search_stored_object(pstatic_stored_object_key k)
Gives a pointer to an object from a key pointer.
bool exists_stored_object(pstatic_stored_object o)
Test if an object is stored.
bool me_is_multithreaded_now()
is the program running in the parallel section
Pointer to a key with a coherent order.
Pointer to an object with the dependencies.
stored_object_tab()
STATIC_STORED_TAB ----------------------------------------------------—.