lugre_listener.cpp

Go to the documentation of this file.
00001 #include "lugre_prefix.h"
00002 #include "lugre_smartptr.h"
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 
00006 namespace Lugre {
00007     
00008 cListenable::cListenable() : iUsageCounter(0), bNeedsCompacting(false) {}
00009 
00010 cListenable::~cListenable() { PROFILE 
00011     if (iUsageCounter != 0) {
00012         PROFILE_PRINT_STACKTRACE
00013         printf("cListenable::Destruct USAGE COUNTER NONZERO ! %d\n",iUsageCounter); 
00014         exit(75);
00015     }
00016 }
00017 
00018 void    cListenable::NotifyAllListeners (const size_t eventcode,void* param) { PROFILE
00019     ++iUsageCounter;
00020     cListener*  pListener;
00021     std::list< std::pair<cSmartPtr<cListener>*,void*> >::iterator       itor,itor_temp;
00022     for (itor = mlListener.begin();itor != mlListener.end();++itor) {
00023         if (!(*itor).first) { PROFILE_PRINT_STACKTRACE printf("cListenable::NotifyAllListeners dead smartptr-ptr\n"); exit(77); }
00024         pListener = **(*itor).first;
00025         if (pListener) {
00026             pListener->Listener_Notify(this,eventcode,param,(*itor).second); // anything might happen in here...
00027         } else {
00028             bNeedsCompacting = true;
00029         }
00030     }
00031     --iUsageCounter;
00032     
00033     // compacting the list : removing dead smart-pointers, this is not allowed during iteration as it can break iterators via callback:unreg
00034     if (bNeedsCompacting && iUsageCounter == 0) {
00035         bNeedsCompacting = false;
00036         // during this procedure no callbacks or notifiers are called, so it is save to remove from the list
00037         for (itor = mlListener.begin();itor != mlListener.end();) {
00038             itor_temp = itor; ++itor; 
00039             // now it doesn't matter if the iterator itor_temp itself is destroyed, 
00040             // but it DOES matter if the next iterator is destroyed, 
00041             // but there are no callbacks where this could happen in during this procedure.
00042             
00043             pListener = **(*itor_temp).first;
00044             if (!pListener) {
00045                 delete  (*itor_temp).first;  // smartptr is no longer needed, this does NOT trigger callback, as smartptr already points to 0
00046                 (*itor_temp).first = 0; // not really neccessary, but useful for debugging, can list entries be manipulated like this ?
00047                 mlListener.erase(itor_temp);
00048             }
00049         }
00050     }
00051 }
00052 
00054 void    cListenable::RegisterListener   (cListener* pListener,void* userdata) { PROFILE 
00055     assert(pListener); 
00056     mlListener.push_back( std::make_pair( new cSmartPtr<cListener>(pListener) , userdata) ); 
00057 }
00058 
00062 void    cListenable::UnRegisterListener (cListener* pListener,void* userdata) { PROFILE
00063     assert(pListener); 
00064     std::list< std::pair<cSmartPtr<cListener>*,void*> >::iterator itor;
00065     for (itor = mlListener.begin();itor != mlListener.end();itor++) {
00066         if (!(*itor).first) { PROFILE_PRINT_STACKTRACE printf("cListenable::UnRegisterListener dead smartptr-ptr\n"); exit(76); }
00067         if (pListener == **(*itor).first && (*itor).second == userdata) {
00068             (*(*itor).first).SmartPtr_SetTarget(0); // let smartptr point to zero (this does not destroy the smartptr)
00069             bNeedsCompacting = true;
00070             // warning, do not remove the listeners from the list, this would be fatal if it happens during iteration
00071             // warning, memory leak. listeners cannot be savely removed during iteration so they are just set to zero. 
00072                 // but this is not a big leak and far better than broken iterators (=bug-search-headache)
00073             return;
00074         }
00075     }
00076 }
00077 
00078 };

Generated on Wed May 23 06:00:14 2012 for cpp by  doxygen 1.5.6