xref: /aoo42x/main/sal/rtl/source/unload.cxx (revision b3bea0d1)
187d2adbcSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
387d2adbcSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
487d2adbcSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
587d2adbcSAndrew Rist  * distributed with this work for additional information
687d2adbcSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
787d2adbcSAndrew Rist  * to you under the Apache License, Version 2.0 (the
887d2adbcSAndrew Rist  * "License"); you may not use this file except in compliance
987d2adbcSAndrew Rist  * with the License.  You may obtain a copy of the License at
1087d2adbcSAndrew Rist  *
1187d2adbcSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1287d2adbcSAndrew Rist  *
1387d2adbcSAndrew Rist  * Unless required by applicable law or agreed to in writing,
1487d2adbcSAndrew Rist  * software distributed under the License is distributed on an
1587d2adbcSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1687d2adbcSAndrew Rist  * KIND, either express or implied.  See the License for the
1787d2adbcSAndrew Rist  * specific language governing permissions and limitations
1887d2adbcSAndrew Rist  * under the License.
1987d2adbcSAndrew Rist  *
2087d2adbcSAndrew Rist  *************************************************************/
2187d2adbcSAndrew Rist 
2287d2adbcSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_sal.hxx"
26cdf0e10cSrcweir #include <rtl/unload.h>
27cdf0e10cSrcweir #include <rtl/alloc.h>
28cdf0e10cSrcweir #include <rtl/ustring.hxx>
29cdf0e10cSrcweir #include <osl/mutex.hxx>
30cdf0e10cSrcweir #include <hash_map>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <functional>
33cdf0e10cSrcweir #include <list>
34cdf0e10cSrcweir #include <deque>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir using osl::MutexGuard;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir //----------------------------------------------------------------------------
39cdf0e10cSrcweir 
40cdf0e10cSrcweir static void rtl_notifyUnloadingListeners();
41cdf0e10cSrcweir 
isEqualTimeValue(const TimeValue * time1,const TimeValue * time2)42cdf0e10cSrcweir static sal_Bool isEqualTimeValue ( const TimeValue* time1,  const TimeValue* time2)
43cdf0e10cSrcweir {
44cdf0e10cSrcweir 	if( time1->Seconds == time2->Seconds &&
45cdf0e10cSrcweir 		time1->Nanosec == time2->Nanosec)
46cdf0e10cSrcweir 		return sal_True;
47cdf0e10cSrcweir 	else
48cdf0e10cSrcweir 		return sal_False;
49cdf0e10cSrcweir }
50cdf0e10cSrcweir 
isGreaterTimeValue(const TimeValue * time1,const TimeValue * time2)51cdf0e10cSrcweir static sal_Bool isGreaterTimeValue(  const TimeValue* time1,  const TimeValue* time2)
52cdf0e10cSrcweir {
53cdf0e10cSrcweir 	sal_Bool retval= sal_False;
54cdf0e10cSrcweir 	if ( time1->Seconds > time2->Seconds)
55cdf0e10cSrcweir 		retval= sal_True;
56cdf0e10cSrcweir 	else if ( time1->Seconds == time2->Seconds)
57cdf0e10cSrcweir 	{
58cdf0e10cSrcweir 		if( time1->Nanosec > time2->Nanosec)
59cdf0e10cSrcweir 			retval= sal_True;
60cdf0e10cSrcweir 	}
61cdf0e10cSrcweir 	return retval;
62cdf0e10cSrcweir }
63cdf0e10cSrcweir 
isGreaterEqualTimeValue(const TimeValue * time1,const TimeValue * time2)64cdf0e10cSrcweir static sal_Bool isGreaterEqualTimeValue( const TimeValue* time1, const TimeValue* time2)
65cdf0e10cSrcweir {
66cdf0e10cSrcweir 	if( isEqualTimeValue( time1, time2) )
67cdf0e10cSrcweir 		return sal_True;
68cdf0e10cSrcweir 	else if( isGreaterTimeValue( time1, time2))
69cdf0e10cSrcweir 		return sal_True;
70cdf0e10cSrcweir 	else
71cdf0e10cSrcweir 		return sal_False;
72cdf0e10cSrcweir }
73cdf0e10cSrcweir 
addTimeValue(const TimeValue * value1,const TimeValue * value2,TimeValue * result)74cdf0e10cSrcweir static void addTimeValue( const TimeValue* value1, const TimeValue* value2, TimeValue* result)
75cdf0e10cSrcweir {
76cdf0e10cSrcweir 	sal_uInt64 sum;
77cdf0e10cSrcweir 	result->Nanosec=0;
78cdf0e10cSrcweir 	result->Seconds=0;
79cdf0e10cSrcweir 
80cdf0e10cSrcweir 	sum= value1->Nanosec + value2->Nanosec;
81cdf0e10cSrcweir 	if( sum >= 1000000000 )
82cdf0e10cSrcweir 	{
83cdf0e10cSrcweir 		result->Seconds=1;
84cdf0e10cSrcweir 		sum -= 1000000000;
85cdf0e10cSrcweir 	}
86cdf0e10cSrcweir 	result->Nanosec= (sal_uInt32)sum;
87cdf0e10cSrcweir 	result->Seconds += value1->Seconds + value2->Seconds;
88cdf0e10cSrcweir }
89cdf0e10cSrcweir 
90cdf0e10cSrcweir 
hasEnoughTimePassed(const TimeValue * unusedSince,const TimeValue * timespan)91cdf0e10cSrcweir static sal_Bool hasEnoughTimePassed( const TimeValue* unusedSince, const TimeValue* timespan)
92cdf0e10cSrcweir {
93cdf0e10cSrcweir 	sal_Bool retval= sal_False;
94cdf0e10cSrcweir 	TimeValue currentTime;
95cdf0e10cSrcweir 	if( osl_getSystemTime( &currentTime))
96cdf0e10cSrcweir 	{
97cdf0e10cSrcweir 		TimeValue addedTime;
98cdf0e10cSrcweir 		addTimeValue( unusedSince, timespan, &addedTime);
99cdf0e10cSrcweir 		if( isGreaterEqualTimeValue( &currentTime, &addedTime))
100cdf0e10cSrcweir 			retval= sal_True;
101cdf0e10cSrcweir 	}
102cdf0e10cSrcweir 
103cdf0e10cSrcweir 	return retval;
104cdf0e10cSrcweir }
105cdf0e10cSrcweir 
getUnloadingMutex()106cdf0e10cSrcweir static osl::Mutex* getUnloadingMutex()
107cdf0e10cSrcweir {
108cdf0e10cSrcweir 	static osl::Mutex * g_pMutex= NULL;
109cdf0e10cSrcweir 	if (!g_pMutex)
110cdf0e10cSrcweir 	{
111cdf0e10cSrcweir 		MutexGuard guard( osl::Mutex::getGlobalMutex() );
112cdf0e10cSrcweir 		if (!g_pMutex)
113cdf0e10cSrcweir 		{
114cdf0e10cSrcweir 			static osl::Mutex g_aMutex;
115cdf0e10cSrcweir 			g_pMutex= &g_aMutex;
116cdf0e10cSrcweir 		}
117cdf0e10cSrcweir 	}
118cdf0e10cSrcweir 	return g_pMutex;
119cdf0e10cSrcweir }
120cdf0e10cSrcweir 
rtl_moduleCount_acquire(rtl_ModuleCount * that)121cdf0e10cSrcweir extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir 	rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
124cdf0e10cSrcweir 	osl_incrementInterlockedCount( &pMod->counter);
125cdf0e10cSrcweir }
126cdf0e10cSrcweir 
rtl_moduleCount_release(rtl_ModuleCount * that)127cdf0e10cSrcweir extern "C" void rtl_moduleCount_release( rtl_ModuleCount * that )
128cdf0e10cSrcweir {
129cdf0e10cSrcweir 	rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
130cdf0e10cSrcweir 	OSL_ENSURE( pMod->counter >0 , "library counter incorrect" );
131cdf0e10cSrcweir 	osl_decrementInterlockedCount( &pMod->counter);
132cdf0e10cSrcweir 	if( pMod->counter == 0)
133cdf0e10cSrcweir 	{
134cdf0e10cSrcweir 		MutexGuard guard( getUnloadingMutex());
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 		if( sal_False == osl_getSystemTime( &pMod->unusedSince) )
137cdf0e10cSrcweir 		{
138cdf0e10cSrcweir 			// set the time to 0 if we could not get the time
139cdf0e10cSrcweir 			pMod->unusedSince.Seconds= 0;
140cdf0e10cSrcweir 			pMod->unusedSince.Nanosec= 0;
141cdf0e10cSrcweir 		}
142cdf0e10cSrcweir 	}
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 
146cdf0e10cSrcweir struct hashModule
147cdf0e10cSrcweir {
operator ()hashModule148cdf0e10cSrcweir 	size_t operator()( const oslModule& rkey) const
149cdf0e10cSrcweir 	{
150cdf0e10cSrcweir 		return (size_t)rkey;
151cdf0e10cSrcweir 	}
152cdf0e10cSrcweir };
153cdf0e10cSrcweir 
154cdf0e10cSrcweir typedef std::hash_map<
15522076bf1SHerbert Dürr 	const oslModule,
156cdf0e10cSrcweir 	std::pair<sal_uInt32, component_canUnloadFunc>,
157cdf0e10cSrcweir 	hashModule,
15822076bf1SHerbert Dürr 	std::equal_to<oslModule>
159cdf0e10cSrcweir > ModuleMap;
160cdf0e10cSrcweir 
161cdf0e10cSrcweir typedef ModuleMap::iterator Mod_IT;
162cdf0e10cSrcweir 
getModuleMap()163cdf0e10cSrcweir static ModuleMap& getModuleMap()
164cdf0e10cSrcweir {
165cdf0e10cSrcweir 	static ModuleMap * g_pMap= NULL;
166cdf0e10cSrcweir 	if (!g_pMap)
167cdf0e10cSrcweir 	{
168cdf0e10cSrcweir 		MutexGuard guard( getUnloadingMutex() );
169cdf0e10cSrcweir 		if (!g_pMap)
170cdf0e10cSrcweir 		{
171cdf0e10cSrcweir 			static ModuleMap g_aModuleMap;
172cdf0e10cSrcweir 			g_pMap= &g_aModuleMap;
173cdf0e10cSrcweir 		}
174cdf0e10cSrcweir 	}
175cdf0e10cSrcweir 	return *g_pMap;
176cdf0e10cSrcweir }
177cdf0e10cSrcweir 
rtl_moduleCount_canUnload(rtl_StandardModuleCount * that,TimeValue * libUnused)178cdf0e10cSrcweir extern "C" sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue * libUnused)
179cdf0e10cSrcweir {
180cdf0e10cSrcweir 	if (that->counter == 0)
181cdf0e10cSrcweir 	{
182cdf0e10cSrcweir 		MutexGuard guard( getUnloadingMutex());
183cdf0e10cSrcweir 		if (libUnused && (that->counter == 0))
184cdf0e10cSrcweir 		{
185cdf0e10cSrcweir 			rtl_copyMemory(libUnused, &that->unusedSince, sizeof(TimeValue));
186cdf0e10cSrcweir 		}
187cdf0e10cSrcweir 	}
188cdf0e10cSrcweir 	return (that->counter == 0);
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 
rtl_registerModuleForUnloading(oslModule module)192cdf0e10cSrcweir extern "C" sal_Bool SAL_CALL rtl_registerModuleForUnloading( oslModule module)
193cdf0e10cSrcweir {
194cdf0e10cSrcweir 	MutexGuard guard( getUnloadingMutex());
195cdf0e10cSrcweir 	ModuleMap& moduleMap= getModuleMap();
196cdf0e10cSrcweir 	sal_Bool ret= sal_True;
197cdf0e10cSrcweir 
198cdf0e10cSrcweir 	// If the module has been registered before, then find it and increment
199cdf0e10cSrcweir 	// its reference cout
200cdf0e10cSrcweir 	Mod_IT it= moduleMap.find( module);
201cdf0e10cSrcweir 	if( it != moduleMap.end())
202cdf0e10cSrcweir 	{
203cdf0e10cSrcweir 		//module already registered, increment ref count
204cdf0e10cSrcweir 		it->second.first++;
205cdf0e10cSrcweir 	}
206cdf0e10cSrcweir 	else
207cdf0e10cSrcweir 	{
208cdf0e10cSrcweir 		// Test if the module supports unloading (exports component_canUnload)
209cdf0e10cSrcweir 		rtl::OUString name(RTL_CONSTASCII_USTRINGPARAM( COMPONENT_CANUNLOAD));
210cdf0e10cSrcweir 		component_canUnloadFunc pFunc=
211cdf0e10cSrcweir 			(component_canUnloadFunc)osl_getFunctionSymbol( module, name.pData);
212cdf0e10cSrcweir 		if (pFunc)
213cdf0e10cSrcweir 		{
214cdf0e10cSrcweir 			//register module for the first time, set ref count to 1
215cdf0e10cSrcweir 			moduleMap[module]= std::make_pair((sal_uInt32)1, pFunc);
216cdf0e10cSrcweir 		}
217cdf0e10cSrcweir 		else
218cdf0e10cSrcweir 			ret= sal_False;
219cdf0e10cSrcweir 	}
220cdf0e10cSrcweir 	return ret;
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
rtl_unregisterModuleForUnloading(oslModule module)223cdf0e10cSrcweir extern "C" void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module)
224cdf0e10cSrcweir {
225cdf0e10cSrcweir 	MutexGuard guard( getUnloadingMutex());
226cdf0e10cSrcweir 
227cdf0e10cSrcweir 	ModuleMap& moduleMap= getModuleMap();
228cdf0e10cSrcweir 	Mod_IT it= moduleMap.find( module);
229cdf0e10cSrcweir 	if( it != moduleMap.end() )
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir 		// The module is registered, decrement ref count.
232cdf0e10cSrcweir 		it->second.first --;
233cdf0e10cSrcweir 
234cdf0e10cSrcweir 		// If the refcount == 0 then remove the module from the map
235cdf0e10cSrcweir 		if( it->second.first == 0)
236cdf0e10cSrcweir 			moduleMap.erase( it);
237cdf0e10cSrcweir 	}
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
rtl_unloadUnusedModules(TimeValue * libUnused)240cdf0e10cSrcweir extern "C" void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused)
241cdf0e10cSrcweir {
242cdf0e10cSrcweir 	MutexGuard guard( getUnloadingMutex());
243cdf0e10cSrcweir 
24422076bf1SHerbert Dürr 	typedef std::list< oslModule > list_type;
245cdf0e10cSrcweir 	list_type unloadedModulesList;
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	ModuleMap& moduleMap= getModuleMap();
248cdf0e10cSrcweir 	Mod_IT it_e= moduleMap.end();
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 	// notify all listeners
251cdf0e10cSrcweir 	rtl_notifyUnloadingListeners();
252cdf0e10cSrcweir 
253*b3bea0d1SJohn Bampton 	// prepare default TimeValue if argument is NULL
254cdf0e10cSrcweir 	TimeValue nullTime={0,0};
255cdf0e10cSrcweir 	TimeValue* pLibUnused= libUnused? libUnused : &nullTime;
256cdf0e10cSrcweir 
257cdf0e10cSrcweir 	Mod_IT it= moduleMap.begin();
258cdf0e10cSrcweir 	for (; it != it_e; ++it)
259cdf0e10cSrcweir 	{
260cdf0e10cSrcweir 		//can the module be unloaded?
261cdf0e10cSrcweir 		component_canUnloadFunc func= it->second.second;
262cdf0e10cSrcweir 		TimeValue unusedSince= {0, 0};
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 		if( func( &unusedSince) )
265cdf0e10cSrcweir 		{
266cdf0e10cSrcweir 			// module can be unloaded if it has not been used at least for the time
267cdf0e10cSrcweir 			// specified by the argument libUnused
268cdf0e10cSrcweir 			if( hasEnoughTimePassed( &unusedSince, pLibUnused))
269cdf0e10cSrcweir 			{
270cdf0e10cSrcweir 				// get the reference count and unload the module as many times
271cdf0e10cSrcweir 				sal_uInt32 refCount= it->second.first;
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 				for ( sal_uInt32 i=0; i < refCount; i++)
274cdf0e10cSrcweir 					osl_unloadModule( it->first);
275cdf0e10cSrcweir 
276cdf0e10cSrcweir 				// mark the module for later removal
277cdf0e10cSrcweir 				unloadedModulesList.push_front( it->first);
278cdf0e10cSrcweir 			}
279cdf0e10cSrcweir 		}
280cdf0e10cSrcweir 	}
281cdf0e10cSrcweir 
282cdf0e10cSrcweir 	// remove all entries containing invalid (unloaded) modules
283cdf0e10cSrcweir 	list_type::const_iterator un_it= unloadedModulesList.begin();
284cdf0e10cSrcweir 	for (; un_it != unloadedModulesList.end(); ++un_it)
285cdf0e10cSrcweir 	{
286cdf0e10cSrcweir 		moduleMap.erase( *un_it);
287cdf0e10cSrcweir 	}
288cdf0e10cSrcweir }
289cdf0e10cSrcweir 
290cdf0e10cSrcweir 
291cdf0e10cSrcweir // ==============================================================================
292cdf0e10cSrcweir // Unloading Listener Administration
293cdf0e10cSrcweir //===============================================================================
294cdf0e10cSrcweir struct hashListener
295cdf0e10cSrcweir {
operator ()hashListener296cdf0e10cSrcweir 	size_t operator()( const sal_Int32& rkey) const
297cdf0e10cSrcweir 	{
298cdf0e10cSrcweir 		return (size_t)rkey;
299cdf0e10cSrcweir 	}
300cdf0e10cSrcweir };
301cdf0e10cSrcweir 
302cdf0e10cSrcweir typedef std::hash_map<
30322076bf1SHerbert Dürr 	const sal_Int32,
304cdf0e10cSrcweir 	std::pair<rtl_unloadingListenerFunc, void*>,
305cdf0e10cSrcweir 	hashListener,
30622076bf1SHerbert Dürr 	std::equal_to<sal_Int32>
307cdf0e10cSrcweir > ListenerMap;
308cdf0e10cSrcweir 
309cdf0e10cSrcweir typedef ListenerMap::iterator Lis_IT;
310cdf0e10cSrcweir 
getListenerMap()311cdf0e10cSrcweir static ListenerMap& getListenerMap()
312cdf0e10cSrcweir {
313cdf0e10cSrcweir 	static ListenerMap * g_pListeners= NULL;
314cdf0e10cSrcweir 	if (!g_pListeners)
315cdf0e10cSrcweir 	{
316cdf0e10cSrcweir 		MutexGuard guard( getUnloadingMutex() );
317cdf0e10cSrcweir 		if (!g_pListeners)
318cdf0e10cSrcweir 		{
319cdf0e10cSrcweir 			static ListenerMap g_aListenerMap;
320cdf0e10cSrcweir 			g_pListeners= &g_aListenerMap;
321cdf0e10cSrcweir 		}
322cdf0e10cSrcweir 	}
323cdf0e10cSrcweir 	return *g_pListeners;
324cdf0e10cSrcweir }
325cdf0e10cSrcweir 
326cdf0e10cSrcweir 
327cdf0e10cSrcweir // This queue contains cookies which have been passed out by rtl_addUnloadingListener and
328cdf0e10cSrcweir // which have been regainded by rtl_removeUnloadingListener. When rtl_addUnloadingListener
329cdf0e10cSrcweir // is called then a cookie has to be returned. First we look into the set if there is one
33086e1cf34SPedro Giffuni // available. Otherwise a new cookie will be provided.
331cdf0e10cSrcweir // not a new value is returned.
332cdf0e10cSrcweir 
33322076bf1SHerbert Dürr typedef std::deque< sal_Int32 > queue_type;
334cdf0e10cSrcweir 
getCookieQueue()335cdf0e10cSrcweir static queue_type& getCookieQueue()
336cdf0e10cSrcweir {
337cdf0e10cSrcweir 	static queue_type * g_pCookies= NULL;
338cdf0e10cSrcweir 	if (!g_pCookies)
339cdf0e10cSrcweir 	{
340cdf0e10cSrcweir 		MutexGuard guard( getUnloadingMutex() );
341cdf0e10cSrcweir 		if (!g_pCookies)
342cdf0e10cSrcweir 		{
343cdf0e10cSrcweir 			static queue_type g_aCookieQueue;
344cdf0e10cSrcweir 			g_pCookies= &g_aCookieQueue;
345cdf0e10cSrcweir 		}
346cdf0e10cSrcweir 	}
347cdf0e10cSrcweir 	return *g_pCookies;
348cdf0e10cSrcweir }
349cdf0e10cSrcweir 
getCookie()350cdf0e10cSrcweir static sal_Int32 getCookie()
351cdf0e10cSrcweir {
352cdf0e10cSrcweir 	static sal_Int32 cookieValue= 1;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 	sal_Int32 retval;
355cdf0e10cSrcweir 	queue_type& regainedCookies= getCookieQueue();
356cdf0e10cSrcweir 	if( regainedCookies.empty() )
357cdf0e10cSrcweir 		retval= cookieValue++;
358cdf0e10cSrcweir 	else
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		retval= regainedCookies.front();
361cdf0e10cSrcweir 		regainedCookies.pop_front();
362cdf0e10cSrcweir 	}
363cdf0e10cSrcweir 	return retval;
364cdf0e10cSrcweir }
365cdf0e10cSrcweir 
recycleCookie(sal_Int32 i)366cdf0e10cSrcweir static inline void recycleCookie( sal_Int32 i)
367cdf0e10cSrcweir {
368cdf0e10cSrcweir 	getCookieQueue().push_back(i);
369cdf0e10cSrcweir }
370cdf0e10cSrcweir 
371cdf0e10cSrcweir 
372cdf0e10cSrcweir // calling the function twice with the same arguments will return tow different cookies.
373cdf0e10cSrcweir // The listener will then notified twice.
374cdf0e10cSrcweir 
375cdf0e10cSrcweir extern "C"
rtl_addUnloadingListener(rtl_unloadingListenerFunc callback,void * _this)376cdf0e10cSrcweir sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this)
377cdf0e10cSrcweir {
378cdf0e10cSrcweir 	MutexGuard guard( getUnloadingMutex());
379cdf0e10cSrcweir 
380cdf0e10cSrcweir 	sal_Int32 cookie= getCookie();
381cdf0e10cSrcweir 	ListenerMap& listenerMap= getListenerMap();
382cdf0e10cSrcweir 	listenerMap[ cookie]= std::make_pair( callback, _this);
383cdf0e10cSrcweir 	return cookie;
384cdf0e10cSrcweir }
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 
387cdf0e10cSrcweir extern "C"
rtl_removeUnloadingListener(sal_Int32 cookie)388cdf0e10cSrcweir void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie )
389cdf0e10cSrcweir {
390cdf0e10cSrcweir 	MutexGuard guard( getUnloadingMutex());
391cdf0e10cSrcweir 
392cdf0e10cSrcweir 	ListenerMap& listenerMap= getListenerMap();
393cdf0e10cSrcweir 	size_t removedElements= listenerMap.erase( cookie);
394cdf0e10cSrcweir 	if( removedElements )
395cdf0e10cSrcweir 		recycleCookie( cookie);
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir 
rtl_notifyUnloadingListeners()399cdf0e10cSrcweir static void rtl_notifyUnloadingListeners()
400cdf0e10cSrcweir {
401cdf0e10cSrcweir 	ListenerMap& listenerMap= getListenerMap();
402cdf0e10cSrcweir 	for( Lis_IT it= listenerMap.begin(); it != listenerMap.end(); ++it)
403cdf0e10cSrcweir 	{
404cdf0e10cSrcweir 		rtl_unloadingListenerFunc callbackFunc= it->second.first;
405cdf0e10cSrcweir 		callbackFunc( it->second.second);
406cdf0e10cSrcweir 	}
407cdf0e10cSrcweir }
408