1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_sal.hxx" 30*cdf0e10cSrcweir #include <rtl/unload.h> 31*cdf0e10cSrcweir #include <rtl/alloc.h> 32*cdf0e10cSrcweir #include <rtl/ustring.hxx> 33*cdf0e10cSrcweir #include <osl/mutex.hxx> 34*cdf0e10cSrcweir #include <hash_map> 35*cdf0e10cSrcweir #include "rtl/allocator.hxx" 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir #include <functional> 38*cdf0e10cSrcweir #include <list> 39*cdf0e10cSrcweir #include <deque> 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir using osl::MutexGuard; 42*cdf0e10cSrcweir 43*cdf0e10cSrcweir //---------------------------------------------------------------------------- 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir static void rtl_notifyUnloadingListeners(); 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir static sal_Bool isEqualTimeValue ( const TimeValue* time1, const TimeValue* time2) 48*cdf0e10cSrcweir { 49*cdf0e10cSrcweir if( time1->Seconds == time2->Seconds && 50*cdf0e10cSrcweir time1->Nanosec == time2->Nanosec) 51*cdf0e10cSrcweir return sal_True; 52*cdf0e10cSrcweir else 53*cdf0e10cSrcweir return sal_False; 54*cdf0e10cSrcweir } 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir static sal_Bool isGreaterTimeValue( const TimeValue* time1, const TimeValue* time2) 57*cdf0e10cSrcweir { 58*cdf0e10cSrcweir sal_Bool retval= sal_False; 59*cdf0e10cSrcweir if ( time1->Seconds > time2->Seconds) 60*cdf0e10cSrcweir retval= sal_True; 61*cdf0e10cSrcweir else if ( time1->Seconds == time2->Seconds) 62*cdf0e10cSrcweir { 63*cdf0e10cSrcweir if( time1->Nanosec > time2->Nanosec) 64*cdf0e10cSrcweir retval= sal_True; 65*cdf0e10cSrcweir } 66*cdf0e10cSrcweir return retval; 67*cdf0e10cSrcweir } 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir static sal_Bool isGreaterEqualTimeValue( const TimeValue* time1, const TimeValue* time2) 70*cdf0e10cSrcweir { 71*cdf0e10cSrcweir if( isEqualTimeValue( time1, time2) ) 72*cdf0e10cSrcweir return sal_True; 73*cdf0e10cSrcweir else if( isGreaterTimeValue( time1, time2)) 74*cdf0e10cSrcweir return sal_True; 75*cdf0e10cSrcweir else 76*cdf0e10cSrcweir return sal_False; 77*cdf0e10cSrcweir } 78*cdf0e10cSrcweir 79*cdf0e10cSrcweir static void addTimeValue( const TimeValue* value1, const TimeValue* value2, TimeValue* result) 80*cdf0e10cSrcweir { 81*cdf0e10cSrcweir sal_uInt64 sum; 82*cdf0e10cSrcweir result->Nanosec=0; 83*cdf0e10cSrcweir result->Seconds=0; 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir sum= value1->Nanosec + value2->Nanosec; 86*cdf0e10cSrcweir if( sum >= 1000000000 ) 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir result->Seconds=1; 89*cdf0e10cSrcweir sum -= 1000000000; 90*cdf0e10cSrcweir } 91*cdf0e10cSrcweir result->Nanosec= (sal_uInt32)sum; 92*cdf0e10cSrcweir result->Seconds += value1->Seconds + value2->Seconds; 93*cdf0e10cSrcweir } 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir 96*cdf0e10cSrcweir static sal_Bool hasEnoughTimePassed( const TimeValue* unusedSince, const TimeValue* timespan) 97*cdf0e10cSrcweir { 98*cdf0e10cSrcweir sal_Bool retval= sal_False; 99*cdf0e10cSrcweir TimeValue currentTime; 100*cdf0e10cSrcweir if( osl_getSystemTime( ¤tTime)) 101*cdf0e10cSrcweir { 102*cdf0e10cSrcweir TimeValue addedTime; 103*cdf0e10cSrcweir addTimeValue( unusedSince, timespan, &addedTime); 104*cdf0e10cSrcweir if( isGreaterEqualTimeValue( ¤tTime, &addedTime)) 105*cdf0e10cSrcweir retval= sal_True; 106*cdf0e10cSrcweir } 107*cdf0e10cSrcweir 108*cdf0e10cSrcweir return retval; 109*cdf0e10cSrcweir } 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir static osl::Mutex* getUnloadingMutex() 112*cdf0e10cSrcweir { 113*cdf0e10cSrcweir static osl::Mutex * g_pMutex= NULL; 114*cdf0e10cSrcweir if (!g_pMutex) 115*cdf0e10cSrcweir { 116*cdf0e10cSrcweir MutexGuard guard( osl::Mutex::getGlobalMutex() ); 117*cdf0e10cSrcweir if (!g_pMutex) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir static osl::Mutex g_aMutex; 120*cdf0e10cSrcweir g_pMutex= &g_aMutex; 121*cdf0e10cSrcweir } 122*cdf0e10cSrcweir } 123*cdf0e10cSrcweir return g_pMutex; 124*cdf0e10cSrcweir } 125*cdf0e10cSrcweir 126*cdf0e10cSrcweir extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that ) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that; 129*cdf0e10cSrcweir osl_incrementInterlockedCount( &pMod->counter); 130*cdf0e10cSrcweir } 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir extern "C" void rtl_moduleCount_release( rtl_ModuleCount * that ) 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that; 135*cdf0e10cSrcweir OSL_ENSURE( pMod->counter >0 , "library counter incorrect" ); 136*cdf0e10cSrcweir osl_decrementInterlockedCount( &pMod->counter); 137*cdf0e10cSrcweir if( pMod->counter == 0) 138*cdf0e10cSrcweir { 139*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 140*cdf0e10cSrcweir 141*cdf0e10cSrcweir if( sal_False == osl_getSystemTime( &pMod->unusedSince) ) 142*cdf0e10cSrcweir { 143*cdf0e10cSrcweir // set the time to 0 if we could not get the time 144*cdf0e10cSrcweir pMod->unusedSince.Seconds= 0; 145*cdf0e10cSrcweir pMod->unusedSince.Nanosec= 0; 146*cdf0e10cSrcweir } 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir } 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir 151*cdf0e10cSrcweir struct hashModule 152*cdf0e10cSrcweir { 153*cdf0e10cSrcweir size_t operator()( const oslModule& rkey) const 154*cdf0e10cSrcweir { 155*cdf0e10cSrcweir return (size_t)rkey; 156*cdf0e10cSrcweir } 157*cdf0e10cSrcweir }; 158*cdf0e10cSrcweir 159*cdf0e10cSrcweir typedef std::hash_map< 160*cdf0e10cSrcweir oslModule, 161*cdf0e10cSrcweir std::pair<sal_uInt32, component_canUnloadFunc>, 162*cdf0e10cSrcweir hashModule, 163*cdf0e10cSrcweir std::equal_to<oslModule>, 164*cdf0e10cSrcweir rtl::Allocator<oslModule> 165*cdf0e10cSrcweir > ModuleMap; 166*cdf0e10cSrcweir 167*cdf0e10cSrcweir typedef ModuleMap::iterator Mod_IT; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir static ModuleMap& getModuleMap() 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir static ModuleMap * g_pMap= NULL; 172*cdf0e10cSrcweir if (!g_pMap) 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex() ); 175*cdf0e10cSrcweir if (!g_pMap) 176*cdf0e10cSrcweir { 177*cdf0e10cSrcweir static ModuleMap g_aModuleMap; 178*cdf0e10cSrcweir g_pMap= &g_aModuleMap; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir } 181*cdf0e10cSrcweir return *g_pMap; 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir 184*cdf0e10cSrcweir extern "C" sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue * libUnused) 185*cdf0e10cSrcweir { 186*cdf0e10cSrcweir if (that->counter == 0) 187*cdf0e10cSrcweir { 188*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 189*cdf0e10cSrcweir if (libUnused && (that->counter == 0)) 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir rtl_copyMemory(libUnused, &that->unusedSince, sizeof(TimeValue)); 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir } 194*cdf0e10cSrcweir return (that->counter == 0); 195*cdf0e10cSrcweir } 196*cdf0e10cSrcweir 197*cdf0e10cSrcweir 198*cdf0e10cSrcweir extern "C" sal_Bool SAL_CALL rtl_registerModuleForUnloading( oslModule module) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 201*cdf0e10cSrcweir ModuleMap& moduleMap= getModuleMap(); 202*cdf0e10cSrcweir sal_Bool ret= sal_True; 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir // If the module has been registered before, then find it and increment 205*cdf0e10cSrcweir // its reference cout 206*cdf0e10cSrcweir Mod_IT it= moduleMap.find( module); 207*cdf0e10cSrcweir if( it != moduleMap.end()) 208*cdf0e10cSrcweir { 209*cdf0e10cSrcweir //module already registered, increment ref count 210*cdf0e10cSrcweir it->second.first++; 211*cdf0e10cSrcweir } 212*cdf0e10cSrcweir else 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir // Test if the module supports unloading (exports component_canUnload) 215*cdf0e10cSrcweir rtl::OUString name(RTL_CONSTASCII_USTRINGPARAM( COMPONENT_CANUNLOAD)); 216*cdf0e10cSrcweir component_canUnloadFunc pFunc= 217*cdf0e10cSrcweir (component_canUnloadFunc)osl_getFunctionSymbol( module, name.pData); 218*cdf0e10cSrcweir if (pFunc) 219*cdf0e10cSrcweir { 220*cdf0e10cSrcweir //register module for the first time, set ref count to 1 221*cdf0e10cSrcweir moduleMap[module]= std::make_pair((sal_uInt32)1, pFunc); 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir else 224*cdf0e10cSrcweir ret= sal_False; 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir return ret; 227*cdf0e10cSrcweir } 228*cdf0e10cSrcweir 229*cdf0e10cSrcweir extern "C" void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module) 230*cdf0e10cSrcweir { 231*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 232*cdf0e10cSrcweir 233*cdf0e10cSrcweir ModuleMap& moduleMap= getModuleMap(); 234*cdf0e10cSrcweir Mod_IT it= moduleMap.find( module); 235*cdf0e10cSrcweir if( it != moduleMap.end() ) 236*cdf0e10cSrcweir { 237*cdf0e10cSrcweir // The module is registered, decrement ref count. 238*cdf0e10cSrcweir it->second.first --; 239*cdf0e10cSrcweir 240*cdf0e10cSrcweir // If the refcount == 0 then remove the module from the map 241*cdf0e10cSrcweir if( it->second.first == 0) 242*cdf0e10cSrcweir moduleMap.erase( it); 243*cdf0e10cSrcweir } 244*cdf0e10cSrcweir } 245*cdf0e10cSrcweir 246*cdf0e10cSrcweir extern "C" void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused) 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir typedef std::list< oslModule, rtl::Allocator<oslModule> > list_type; 251*cdf0e10cSrcweir list_type unloadedModulesList; 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir ModuleMap& moduleMap= getModuleMap(); 254*cdf0e10cSrcweir Mod_IT it_e= moduleMap.end(); 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir // notify all listeners 257*cdf0e10cSrcweir rtl_notifyUnloadingListeners(); 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir // prepare default TimeValue if argumetn is NULL 260*cdf0e10cSrcweir TimeValue nullTime={0,0}; 261*cdf0e10cSrcweir TimeValue* pLibUnused= libUnused? libUnused : &nullTime; 262*cdf0e10cSrcweir 263*cdf0e10cSrcweir Mod_IT it= moduleMap.begin(); 264*cdf0e10cSrcweir for (; it != it_e; ++it) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir //can the module be unloaded? 267*cdf0e10cSrcweir component_canUnloadFunc func= it->second.second; 268*cdf0e10cSrcweir TimeValue unusedSince= {0, 0}; 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir if( func( &unusedSince) ) 271*cdf0e10cSrcweir { 272*cdf0e10cSrcweir // module can be unloaded if it has not been used at least for the time 273*cdf0e10cSrcweir // specified by the argument libUnused 274*cdf0e10cSrcweir if( hasEnoughTimePassed( &unusedSince, pLibUnused)) 275*cdf0e10cSrcweir { 276*cdf0e10cSrcweir // get the reference count and unload the module as many times 277*cdf0e10cSrcweir sal_uInt32 refCount= it->second.first; 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir for ( sal_uInt32 i=0; i < refCount; i++) 280*cdf0e10cSrcweir osl_unloadModule( it->first); 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir // mark the module for later removal 283*cdf0e10cSrcweir unloadedModulesList.push_front( it->first); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir // remove all entries containing invalid (unloaded) modules 289*cdf0e10cSrcweir list_type::const_iterator un_it= unloadedModulesList.begin(); 290*cdf0e10cSrcweir for (; un_it != unloadedModulesList.end(); ++un_it) 291*cdf0e10cSrcweir { 292*cdf0e10cSrcweir moduleMap.erase( *un_it); 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir // ============================================================================== 298*cdf0e10cSrcweir // Unloading Listener Administration 299*cdf0e10cSrcweir //=============================================================================== 300*cdf0e10cSrcweir struct hashListener 301*cdf0e10cSrcweir { 302*cdf0e10cSrcweir size_t operator()( const sal_Int32& rkey) const 303*cdf0e10cSrcweir { 304*cdf0e10cSrcweir return (size_t)rkey; 305*cdf0e10cSrcweir } 306*cdf0e10cSrcweir }; 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir typedef std::hash_map< 309*cdf0e10cSrcweir sal_Int32, 310*cdf0e10cSrcweir std::pair<rtl_unloadingListenerFunc, void*>, 311*cdf0e10cSrcweir hashListener, 312*cdf0e10cSrcweir std::equal_to<sal_Int32>, 313*cdf0e10cSrcweir rtl::Allocator<sal_Int32> 314*cdf0e10cSrcweir > ListenerMap; 315*cdf0e10cSrcweir 316*cdf0e10cSrcweir typedef ListenerMap::iterator Lis_IT; 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir static ListenerMap& getListenerMap() 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir static ListenerMap * g_pListeners= NULL; 321*cdf0e10cSrcweir if (!g_pListeners) 322*cdf0e10cSrcweir { 323*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex() ); 324*cdf0e10cSrcweir if (!g_pListeners) 325*cdf0e10cSrcweir { 326*cdf0e10cSrcweir static ListenerMap g_aListenerMap; 327*cdf0e10cSrcweir g_pListeners= &g_aListenerMap; 328*cdf0e10cSrcweir } 329*cdf0e10cSrcweir } 330*cdf0e10cSrcweir return *g_pListeners; 331*cdf0e10cSrcweir } 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir // This queue contains cookies which have been passed out by rtl_addUnloadingListener and 335*cdf0e10cSrcweir // which have been regainded by rtl_removeUnloadingListener. When rtl_addUnloadingListener 336*cdf0e10cSrcweir // is called then a cookie has to be returned. First we look into the set if there is one 337*cdf0e10cSrcweir // availabe. Otherwise a new cookie will be provided. 338*cdf0e10cSrcweir // not a new value is returned. 339*cdf0e10cSrcweir 340*cdf0e10cSrcweir typedef std::deque< 341*cdf0e10cSrcweir sal_Int32, 342*cdf0e10cSrcweir rtl::Allocator<sal_Int32> 343*cdf0e10cSrcweir > queue_type; 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir static queue_type& getCookieQueue() 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir static queue_type * g_pCookies= NULL; 348*cdf0e10cSrcweir if (!g_pCookies) 349*cdf0e10cSrcweir { 350*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex() ); 351*cdf0e10cSrcweir if (!g_pCookies) 352*cdf0e10cSrcweir { 353*cdf0e10cSrcweir static queue_type g_aCookieQueue; 354*cdf0e10cSrcweir g_pCookies= &g_aCookieQueue; 355*cdf0e10cSrcweir } 356*cdf0e10cSrcweir } 357*cdf0e10cSrcweir return *g_pCookies; 358*cdf0e10cSrcweir } 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir static sal_Int32 getCookie() 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir static sal_Int32 cookieValue= 1; 363*cdf0e10cSrcweir 364*cdf0e10cSrcweir sal_Int32 retval; 365*cdf0e10cSrcweir queue_type& regainedCookies= getCookieQueue(); 366*cdf0e10cSrcweir if( regainedCookies.empty() ) 367*cdf0e10cSrcweir retval= cookieValue++; 368*cdf0e10cSrcweir else 369*cdf0e10cSrcweir { 370*cdf0e10cSrcweir retval= regainedCookies.front(); 371*cdf0e10cSrcweir regainedCookies.pop_front(); 372*cdf0e10cSrcweir } 373*cdf0e10cSrcweir return retval; 374*cdf0e10cSrcweir } 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir static inline void recycleCookie( sal_Int32 i) 377*cdf0e10cSrcweir { 378*cdf0e10cSrcweir getCookieQueue().push_back(i); 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir // calling the function twice with the same arguments will return tow different cookies. 383*cdf0e10cSrcweir // The listener will then notified twice. 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir extern "C" 386*cdf0e10cSrcweir sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this) 387*cdf0e10cSrcweir { 388*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 389*cdf0e10cSrcweir 390*cdf0e10cSrcweir sal_Int32 cookie= getCookie(); 391*cdf0e10cSrcweir ListenerMap& listenerMap= getListenerMap(); 392*cdf0e10cSrcweir listenerMap[ cookie]= std::make_pair( callback, _this); 393*cdf0e10cSrcweir return cookie; 394*cdf0e10cSrcweir } 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir extern "C" 398*cdf0e10cSrcweir void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie ) 399*cdf0e10cSrcweir { 400*cdf0e10cSrcweir MutexGuard guard( getUnloadingMutex()); 401*cdf0e10cSrcweir 402*cdf0e10cSrcweir ListenerMap& listenerMap= getListenerMap(); 403*cdf0e10cSrcweir size_t removedElements= listenerMap.erase( cookie); 404*cdf0e10cSrcweir if( removedElements ) 405*cdf0e10cSrcweir recycleCookie( cookie); 406*cdf0e10cSrcweir } 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir static void rtl_notifyUnloadingListeners() 410*cdf0e10cSrcweir { 411*cdf0e10cSrcweir ListenerMap& listenerMap= getListenerMap(); 412*cdf0e10cSrcweir for( Lis_IT it= listenerMap.begin(); it != listenerMap.end(); ++it) 413*cdf0e10cSrcweir { 414*cdf0e10cSrcweir rtl_unloadingListenerFunc callbackFunc= it->second.first; 415*cdf0e10cSrcweir callbackFunc( it->second.second); 416*cdf0e10cSrcweir } 417*cdf0e10cSrcweir } 418