34 #define DAL_STORED_OBJECT_DEBUG_NOISY 2
36 #if DAL_STORED_OBJECT_DEBUG
38 static bool dal_static_stored_tab_valid__ =
true;
40 #define STORED_ASSERT(test, message) GMM_ASSERT1(test, message);
41 #define ON_STORED_DEBUG(expression) expression;
43 static std::map <const static_stored_object *, std::string> _created_objects;
44 static std::map <const static_stored_object *, std::string> _added_objects;
45 static std::map <const static_stored_object *, std::string> _deleted_objects;
48 void stored_debug_created(
const static_stored_object *o,
49 const std::string &name) {
50 if (dal_static_stored_tab_valid__) {
51 _created_objects[o] = name;
52 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
53 cout <<
"Created " << name <<
" : " << o << endl;
57 void stored_debug_added(
const static_stored_object *o) {
58 if (dal_static_stored_tab_valid__) {
59 auto it = _created_objects.find(o);
60 if (it == _created_objects.end()) {
61 _added_objects[o] =
"";
62 # if DAL_STORED_OBJECT_DEBUG_NOISY > 0
63 cout <<
"Adding an unknown object " << o <<
" of type "
64 <<
typeid(*o).name() <<
" add DAL_STORED_OBJECT_DEBUG_CREATED"
65 "(o, name) in its constructor" << endl;
68 _added_objects[o] = it->second;
69 _created_objects.erase(it);
70 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
71 cout <<
"Added " << it->second <<
" : " << o << endl;
74 if (_deleted_objects.size()) {
75 cout << endl <<
"Number of stored objects: " << _added_objects.size()
76 << endl <<
"Number of unstored created objects: "
77 << _created_objects.size() << endl
78 <<
"Number of undestroyed object: "
79 << _deleted_objects.size() << endl;
80 for (
auto &x : _deleted_objects)
81 cout <<
"UNDESTROYED OBJECT " << x.second <<
" : " << x.first << endl;
86 void stored_debug_deleted(
const static_stored_object *o) {
87 if (dal_static_stored_tab_valid__) {
88 auto it = _added_objects.find(o);
89 if (it == _added_objects.end()) {
90 cout <<
"Deleting an unknown object ! " << o << endl;
91 _deleted_objects[o] =
"";
93 _deleted_objects[o] = it->second;
94 _added_objects.erase(it);
95 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
96 cout <<
"Deleted " << it->second <<
" : " << o << endl;
102 void stored_debug_destroyed(
const static_stored_object *o,
103 const std::string &name) {
104 if (dal_static_stored_tab_valid__) {
105 auto it = _deleted_objects.find(o);
106 if (it == _deleted_objects.end()) {
107 it = _created_objects.find(o);
108 if (it == _created_objects.end()) {
109 it = _added_objects.find(o);
110 if (it == _added_objects.end()) {
111 cout <<
"Destroy an unknown object ! " << o <<
" name given : "
114 _added_objects.erase(it);
115 cout <<
"Destroy a non deleted object !! " << o <<
" name given : "
119 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
120 cout <<
"Destroy an unadded object " << it->second <<
" : "
123 _created_objects.erase(it);
126 # if DAL_STORED_OBJECT_DEBUG_NOISY > 1
127 cout <<
"Destroy " << it->second <<
" : " << o <<
" name given : "
130 _deleted_objects.erase(it);
137 #define STORED_ASSERT(test, message)
138 #define ON_STORED_DEBUG(expression)
143 pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o,
size_t thread){
145 STORED_ASSERT(dal_static_stored_tab_valid__,
"Too late to do that");
146 auto it = stored_keys.find(o);
147 if (it != stored_keys.end())
return it->second;
152 pstatic_stored_object_key key_of_stored_object_other_threads(pstatic_stored_object o){
156 auto key = key_of_stored_object(o,thread);
162 pstatic_stored_object_key key_of_stored_object(pstatic_stored_object o){
166 key_of_stored_object_other_threads(o) : nullptr;
172 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return false)
173 return (stored_keys.find(o) != stored_keys.end());
178 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return nullptr)
179 return stored_objects.search_stored_object(k);
182 pstatic_stored_object search_stored_object_on_all_threads(pstatic_stored_object_key k){
184 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return nullptr)
185 auto p = stored_objects.search_stored_object(k);
188 for(
size_t thread = 0; thread < singleton<stored_object_tab>::num_threads(); ++thread){
191 p = other_objects.search_stored_object(k);
197 std::pair<stored_object_tab::iterator, stored_object_tab::iterator>
198 iterators_of_object(pstatic_stored_object o){
201 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
202 auto it = stored_objects.iterator_of_object_(o);
203 if (it != stored_objects.end())
return {it, stored_objects.end()};
213 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
214 auto& stored_keys = stored_objects.stored_keys_;
216 GMM_ASSERT1(stored_objects.size() == stored_keys.size(),
217 "keys and objects tables don't match");
218 for (
auto &&pair : stored_keys){
219 auto itos = iterators_of_object(pair.first);
220 GMM_ASSERT1(itos.first != itos.second,
"Key without object is found");
222 for (
auto &&pair : stored_objects){
223 auto itos = iterators_of_object(pair.second.p);
224 GMM_ASSERT1(itos.first != itos.second,
"Object has key but cannot be found");
230 pstatic_stored_object o2) {
231 bool dep_added =
false;
234 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return)
235 if ((dep_added = stored_objects.add_dependency_(o1,o2)))
break;
237 GMM_ASSERT1(dep_added,
"Failed to add dependency between " << o1
238 <<
" of type " <<
typeid(*o1).name() <<
" and " << o2
239 <<
" of type " <<
typeid(*o2).name() <<
". ");
241 bool dependent_added =
false;
244 if ((dependent_added = stored_objects.add_dependent_(o1,o2)))
break;
246 GMM_ASSERT1(dependent_added,
"Failed to add dependent between " << o1
247 <<
" of type " <<
typeid(*o1).name() <<
" and " << o2
248 <<
" of type " <<
typeid(*o2).name() <<
". ");
256 bool dep_deleted =
false;
259 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return false)
260 if ((dep_deleted = stored_objects.del_dependency_(o1,o2)))
break;
262 GMM_ASSERT1(dep_deleted,
"Failed to delete dependency between " << o1 <<
" of type "
263 <<
typeid(*o1).name() <<
" and " << o2 <<
" of type "
264 <<
typeid(*o2).name() <<
". ");
266 bool dependent_deleted =
false;
267 bool dependent_empty =
false;
270 dependent_deleted = stored_objects.del_dependent_(o1,o2);
271 if (dependent_deleted){
272 dependent_empty = stored_objects.has_dependent_objects(o2);
276 GMM_ASSERT1(dependent_deleted,
"Failed to delete dependent between " << o1 <<
" of type "
277 <<
typeid(*o1).name() <<
" and " << o2 <<
" of type "
278 <<
typeid(*o2).name() <<
". ");
280 return dependent_empty;
285 STORED_ASSERT(dal_static_stored_tab_valid__,
"Too late to add an object");
287 stored_objects.add_stored_object(k,o,perm);
290 void basic_delete(std::list<pstatic_stored_object> &to_delete){
293 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
return)
294 stored_objects_this_thread.basic_delete_(to_delete);
296 if (!to_delete.empty()){
300 stored_objects.basic_delete_(to_delete);
301 if (to_delete.empty())
break;
305 if (!to_delete.empty()) GMM_WARNING1(
"Not all objects were deleted");
307 else{GMM_ASSERT1(to_delete.empty(),
"Could not delete objects");}
311 bool ignore_unstored) {
315 ON_STORED_DEBUG(
if (dal_static_stored_tab_valid__)
return);
317 std::list<pstatic_stored_object>::iterator it, itnext;
318 for (it = to_delete.begin(); it != to_delete.end(); it = itnext) {
319 itnext = it; itnext++;
321 auto itos = iterators_of_object(*it);
322 if (itos.first == itos.second) {
323 if (ignore_unstored) to_delete.erase(it);
325 GMM_WARNING1(
"This object is (already?) not stored : "<< it->get()
326 <<
" typename: " <<
typeid(*it->get()).name()
327 <<
"(which could happen in multithreaded code and is OK)");
329 GMM_ASSERT1(
false,
"This object is not stored : " << it->get()
330 <<
" typename: " <<
typeid(*it->get()).name());
333 else itos.first->second.valid =
false;
336 for (
auto &&pobj : to_delete) {
338 auto itos = iterators_of_object(pobj);
339 GMM_ASSERT1(itos.first != itos.second,
"An object disapeared !");
340 itos.first->second.valid =
false;
341 auto second_dep = itos.first->second.dependencies;
342 for (
const auto &pdep : second_dep) {
344 auto itods = iterators_of_object(pdep);
345 if (itods.first->second.perm == AUTODELETE_STATIC_OBJECT
346 && itods.first->second.valid) {
347 itods.first->second.valid =
false;
348 to_delete.push_back(pdep);
352 for (
auto &&pdep : itos.first->second.dependent_object) {
353 auto itods = iterators_of_object(pdep);
354 if (itods.first != itods.second) {
355 GMM_ASSERT1(itods.first->second.perm != PERMANENT_STATIC_OBJECT,
356 "Trying to delete a permanent object " << pdep);
357 if (itods.first->second.valid) {
358 itods.first->second.valid =
false;
359 to_delete.push_back(itods.first->second.p);
365 basic_delete(to_delete);
369 std::list<pstatic_stored_object> to_delete;
370 to_delete.push_back(o);
376 std::list<pstatic_stored_object> to_delete;
379 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
380 if (perm == PERMANENT_STATIC_OBJECT) perm = STRONG_STATIC_OBJECT;
381 for (
auto &&pair : stored_objects){
382 if (pair.second.perm >= perm) to_delete.push_back(pair.second.p);
391 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
392 if (stored_keys.begin() == stored_keys.end())
393 ost <<
"No static stored objects" << endl;
394 else ost <<
"Static stored objects" << endl;
395 for (
const auto &t : stored_keys)
396 ost <<
"Object: " << t.first <<
" typename: "
397 <<
typeid(*(t.first)).name() << endl;
402 long num_objects = 0;
405 ON_STORED_DEBUG(
if (!dal_static_stored_tab_valid__)
continue;)
406 num_objects += stored_keys.size();
416 locks_{}, stored_keys_{}{
417 ON_STORED_DEBUG(dal_static_stored_tab_valid__ =
true;)
420 stored_object_tab::~stored_object_tab(){
421 ON_STORED_DEBUG(dal_static_stored_tab_valid__ =
false;)
424 pstatic_stored_object
425 stored_object_tab::search_stored_object(pstatic_stored_object_key k)
const{
426 auto guard = locks_.get_lock();
427 auto it = find(enr_static_stored_object_key(k));
428 return (it != end()) ? it->second.p :
nullptr;
431 bool stored_object_tab::add_dependency_(pstatic_stored_object o1,
432 pstatic_stored_object o2){
433 auto guard = locks_.get_lock();
434 auto it = stored_keys_.find(o1);
435 if (it == stored_keys_.end())
return false;
436 auto ito1 = find(it->second);
437 GMM_ASSERT1(ito1 != end(),
"Object has a key, but cannot be found");
438 ito1->second.dependencies.insert(o2);
442 void stored_object_tab::add_stored_object(pstatic_stored_object_key k,
443 pstatic_stored_object o, permanence perm){
444 DAL_STORED_OBJECT_DEBUG_ADDED(o.get());
445 auto guard = locks_.get_lock();
446 GMM_ASSERT1(stored_keys_.find(o) == stored_keys_.end(),
447 "This object has already been stored, possibly with another key");
449 insert(std::make_pair(enr_static_stored_object_key(k),
450 enr_static_stored_object(o, perm)));
452 GMM_ASSERT2(stored_keys_.size() == size() && t !=
size_t(-1),
453 "stored_keys are not consistent with stored_object tab");
456 bool stored_object_tab::add_dependent_(pstatic_stored_object o1,
457 pstatic_stored_object o2){
458 auto guard = locks_.get_lock();
459 auto it = stored_keys_.find(o2);
460 if (it == stored_keys_.end())
return false;
461 auto ito2 = find(it->second);
462 GMM_ASSERT1(ito2 != end(),
"Object has a key, but cannot be found");
463 ito2->second.dependent_object.insert(o1);
467 bool stored_object_tab::del_dependency_(pstatic_stored_object o1,
468 pstatic_stored_object o2){
469 auto guard = locks_.get_lock();
470 auto it1 = stored_keys_.find(o1);
471 if (it1 == stored_keys_.end())
return false;
472 auto ito1 = find(it1->second);
473 GMM_ASSERT1(ito1 != end(),
"Object has a key, but cannot be found");
474 ito1->second.dependencies.erase(o2);
478 stored_object_tab::iterator stored_object_tab
479 ::iterator_of_object_(pstatic_stored_object o){
480 auto itk = stored_keys_.find(o);
481 if (itk == stored_keys_.end())
return end();
482 auto ito = find(itk->second);
483 GMM_ASSERT1(ito != end(),
"Object has a key, but is not stored");
487 bool stored_object_tab::del_dependent_(pstatic_stored_object o1,
488 pstatic_stored_object o2){
489 auto guard = locks_.get_lock();
490 auto it2 = stored_keys_.find(o2);
491 if (it2 == stored_keys_.end())
return false;
492 auto ito2 = find(it2->second);
493 GMM_ASSERT1(ito2 != end(),
"Object has a key, but cannot be found");
494 ito2->second.dependent_object.erase(o1);
498 bool stored_object_tab::exists_stored_object(pstatic_stored_object o)
const{
499 auto guard = locks_.get_lock();
500 return (stored_keys_.find(o) != stored_keys_.end());
503 bool stored_object_tab::has_dependent_objects(pstatic_stored_object o)
const{
504 auto guard = locks_.get_lock();
505 auto it = stored_keys_.find(o);
506 GMM_ASSERT1(it != stored_keys_.end(),
"Object is not stored");
507 auto ito = find(it->second);
508 GMM_ASSERT1(ito != end(),
"Object has a key, but cannot be found");
509 return ito->second.dependent_object.empty();
512 void stored_object_tab::basic_delete_(std::list<pstatic_stored_object> &to_delete){
513 auto guard = locks_.get_lock();
514 for (
auto it = to_delete.begin(); it != to_delete.end();){
515 DAL_STORED_OBJECT_DEBUG_DELETED(it->get());
516 auto itk = stored_keys_.find(*it);
518 if (itk != stored_keys_.end()){
519 ito = find(itk->second);
520 stored_keys_.erase(itk);
524 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 ----------------------------------------------------—.