xref: /aoo41x/main/sal/inc/rtl/unload.h (revision cdf0e10c)
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 #ifndef _RTL_UNLOAD_H_
28*cdf0e10cSrcweir #define _RTL_UNLOAD_H_
29*cdf0e10cSrcweir 
30*cdf0e10cSrcweir #include <sal/types.h>
31*cdf0e10cSrcweir #include <osl/time.h>
32*cdf0e10cSrcweir #include <osl/interlck.h>
33*cdf0e10cSrcweir #include <osl/module.h>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir ///@HTML
36*cdf0e10cSrcweir /** @file
37*cdf0e10cSrcweir The API enables an effective way of unloading libraries in a centralized way.
38*cdf0e10cSrcweir The mechanism ensures that used libraries are not unloaded. This prevents
39*cdf0e10cSrcweir crashes if library code is being used after unloading the library.
40*cdf0e10cSrcweir The unloading mechanism currently only works with libraries which contain
41*cdf0e10cSrcweir UNO services. A library cannot be unloaded if one of the following conditions
42*cdf0e10cSrcweir apply
43*cdf0e10cSrcweir 
44*cdf0e10cSrcweir <ul>
45*cdf0e10cSrcweir <li>An instance is still referenced </li>
46*cdf0e10cSrcweir <li>A module has been loaded without registering it </li>
47*cdf0e10cSrcweir <li>The service manager has created a one instance service </li>
48*cdf0e10cSrcweir <li>A service instance has been added to an UNO context </li>
49*cdf0e10cSrcweir </ul>
50*cdf0e10cSrcweir 
51*cdf0e10cSrcweir <b>Notification Mechanism</b>
52*cdf0e10cSrcweir The API provides a notification mechanism. Clients can use it to do clean up,
53*cdf0e10cSrcweir such as releasing cached references, in order to allow modules to be unloaded.
54*cdf0e10cSrcweir As long as someone holds a reference to an object whose housing module
55*cdf0e10cSrcweir supports unloading the module cannot be unloaded.<p>
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir Because of the inherent danger of crashing the application by using this API
58*cdf0e10cSrcweir all instances which control threads should be registered listeners. On
59*cdf0e10cSrcweir notification they have to ensure that their threads assume a safe state, that
60*cdf0e10cSrcweir is, they run outside of modules which could be unloaded and do not jump
61*cdf0e10cSrcweir back into module code as a result of a finished function call. In other words,
62*cdf0e10cSrcweir there must not be an address of the module on the thread's stack.
63*cdf0e10cSrcweir <p>
64*cdf0e10cSrcweir Since current operating systems lack APIs in respect to controlling the
65*cdf0e10cSrcweir position of threads within libraries, it would be a major effort to comply with
66*cdf0e10cSrcweir that recommendation. The best and most efficient way of handling the unloading
67*cdf0e10cSrcweir scenario is to let all threads, except for the main thread, die in case of a
68*cdf0e10cSrcweir notification.
69*cdf0e10cSrcweir <p>
70*cdf0e10cSrcweir Use this API with great care because it might crash the application. See the
71*cdf0e10cSrcweir respective documentation (Library Unloading) on the udk.openoffice.org web site.
72*cdf0e10cSrcweir */
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir 
75*cdf0e10cSrcweir /**
76*cdf0e10cSrcweir A library which supports unloading has to implement and export a function
77*cdf0e10cSrcweir called <code>component_canUnload</code>. <p>
78*cdf0e10cSrcweir If the function returns <code>sal_True</code> then the module can be safely unloaded.
79*cdf0e10cSrcweir That is the case when there are no external references to code within the
80*cdf0e10cSrcweir library. In case a module houses UNO components then the function must return
81*cdf0e10cSrcweir <code>sal_False</code> after the first factory has been handed out. The function then
82*cdf0e10cSrcweir continues to return <code>sal_False</code> as long as there is at least one object (factory
83*cdf0e10cSrcweir or service instance)  which originated from the module.<p>
84*cdf0e10cSrcweir 
85*cdf0e10cSrcweir Libraries which not only contain UNO components (or none at all) have to
86*cdf0e10cSrcweir provide a means to control whether they can be unloaded or not, e.g. However,
87*cdf0e10cSrcweir there is no concept yet. <p>
88*cdf0e10cSrcweir 
89*cdf0e10cSrcweir The argument <code>pTime</code> is an optional out-parameter. If the return value is
90*cdf0e10cSrcweir <code>sal_True</code> then <code>pTime</code> reflects a point in time since
91*cdf0e10cSrcweir when the module could have
92*cdf0e10cSrcweir been unloaded. Since that time the function would have continually returned
93*cdf0e10cSrcweir <code>sal_True</code> up to the present. The value of <code>pTime</code> is
94*cdf0e10cSrcweir important for the decision
95*cdf0e10cSrcweir as to a module will be unloaded. When someone initiates the unloading of
96*cdf0e10cSrcweir modules by calling <code>rtl_unloadUnusedModules</code> then the caller can specify a time
97*cdf0e10cSrcweir span with the effect that only those modules are unloaded which are unused at
98*cdf0e10cSrcweir least for that amount of time. If <code>component_canUnload</code> does not
99*cdf0e10cSrcweir fill in <code>pTime</code>
100*cdf0e10cSrcweir then the module is unloaded immediately.<p>
101*cdf0e10cSrcweir 
102*cdf0e10cSrcweir <code>component_canUnload</code> is implicitly called by <code>rtl_unloadUnusedModules
103*cdf0e10cSrcweir </code>. There is no need to call the function directly.
104*cdf0e10cSrcweir */
105*cdf0e10cSrcweir #define COMPONENT_CANUNLOAD			"component_canUnload"
106*cdf0e10cSrcweir typedef sal_Bool (SAL_CALL * component_canUnloadFunc)( TimeValue* pTime);
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir /** C-interface for a module reference counting
110*cdf0e10cSrcweir  */
111*cdf0e10cSrcweir #ifdef __cplusplus
112*cdf0e10cSrcweir extern "C"
113*cdf0e10cSrcweir {
114*cdf0e10cSrcweir #endif
115*cdf0e10cSrcweir 
116*cdf0e10cSrcweir /**
117*cdf0e10cSrcweir By registering a module, one declares that a module supports the
118*cdf0e10cSrcweir unloading mechanism. One registers a module by calling this function.<p>
119*cdf0e10cSrcweir 
120*cdf0e10cSrcweir A module can only be unloaded from memory when it has been registered
121*cdf0e10cSrcweir as many times as it has been loaded. The reason is that a library can
122*cdf0e10cSrcweir be &quot;loaded&quot; several times by <code>osl_loadModule</code>
123*cdf0e10cSrcweir within the same process. The
124*cdf0e10cSrcweir function will then return the same module handle because the library will
125*cdf0e10cSrcweir effectively only be loaded once. To remove the library from memory it is
126*cdf0e10cSrcweir necessary to call <code>osl_unloadModule</code> as often as <code>
127*cdf0e10cSrcweir osl_loadModule</code> was called. The
128*cdf0e10cSrcweir function <code>rtl_unloadUnusedModules</code> calls <code>osl_unloadModule</code>
129*cdf0e10cSrcweir for a module as many
130*cdf0e10cSrcweir times as it was registered. If, for example, a module has been registered one
131*cdf0e10cSrcweir time less then <code>osl_loadModule</code> has been called and the module can be unloaded
132*cdf0e10cSrcweir then it needs a call to <code>rtl_unloadUnusedModules</code> and an explicit call to
133*cdf0e10cSrcweir <code>osl_unloadModule</code> to remove the module from memory. <p>
134*cdf0e10cSrcweir 
135*cdf0e10cSrcweir A module must be registered every time it has been loaded otherwise the
136*cdf0e10cSrcweir unloading mechanism is not effective.<p>
137*cdf0e10cSrcweir 
138*cdf0e10cSrcweir Before a module is registered, one has to make sure that the module is in a
139*cdf0e10cSrcweir state that prevents it from being unloaded. In other words,
140*cdf0e10cSrcweir <code>component_canUnload</code> must return <code>sal_False</code>. Assuming that
141*cdf0e10cSrcweir <code>component_canUnload</code>
142*cdf0e10cSrcweir returns <code>sal_True</code> and it is registered regardless, then a call to
143*cdf0e10cSrcweir <code>rtl_unloadUnusedModules</code> causes the module to be unloaded. This unloading can
144*cdf0e10cSrcweir be set off by a different thread and the thread which registered the module is
145*cdf0e10cSrcweir &quot;unaware&quot; of this. Then when the first thread tries to obtain a factory or
146*cdf0e10cSrcweir calls another function in the module, the application will crash, because the
147*cdf0e10cSrcweir module has been unloaded before. Therefore one has to ensure that the module
148*cdf0e10cSrcweir cannot be unloaded before it is registered. This is simply done by obtaining a
149*cdf0e10cSrcweir factory from the module. As long as a factory or some other object, which has
150*cdf0e10cSrcweir been created by the factory, is alive, the <code>component_canUnload</code> function will
151*cdf0e10cSrcweir return <code>sal_False</code>.<p>
152*cdf0e10cSrcweir Loading and registering have to be in this order:<br>
153*cdf0e10cSrcweir <ul>
154*cdf0e10cSrcweir <li>load a library (<code>osl_loadModule</code>)</li>
155*cdf0e10cSrcweir <li>get the <code>component_getFactory</code> function and get a factory</li>
156*cdf0e10cSrcweir <li>register the module (rtl_registerModuleForUnloading</li>
157*cdf0e10cSrcweir </ul>
158*cdf0e10cSrcweir Usually the service manager is used to obtain an instance of a service.
159*cdf0e10cSrcweir The service manager registers all modules which support the unloading mechanism.
160*cdf0e10cSrcweir When the service manager is used to get service instances than one does not
161*cdf0e10cSrcweir have to bother about registering.
162*cdf0e10cSrcweir 
163*cdf0e10cSrcweir @param module a module handle as is obtained by osl_loadModule
164*cdf0e10cSrcweir @return sal_True - the module could be registered for unloading, sal_False otherwise
165*cdf0e10cSrcweir */
166*cdf0e10cSrcweir sal_Bool SAL_CALL rtl_registerModuleForUnloading( oslModule module);
167*cdf0e10cSrcweir 
168*cdf0e10cSrcweir /**
169*cdf0e10cSrcweir The function revokes the registration of a module. By calling the function for
170*cdf0e10cSrcweir a previously registered module one prevents the module from being unloaded by
171*cdf0e10cSrcweir this unloading mechanism. However, in order to completely unregister the module
172*cdf0e10cSrcweir it is necessary to call the function as often as the module has been registered.
173*cdf0e10cSrcweir <p>
174*cdf0e10cSrcweir <code>rtl_unloadUnusedModules</code> unregisters the modules which it unloads. Therefore
175*cdf0e10cSrcweir there is no need to call this function unless one means to prevent the unloading of a module.
176*cdf0e10cSrcweir 
177*cdf0e10cSrcweir @param module a module handle as is obtained by osl_loadModule
178*cdf0e10cSrcweir */
179*cdf0e10cSrcweir void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module);
180*cdf0e10cSrcweir /**
181*cdf0e10cSrcweir This function sets off the unloading mechanism. At first it notifies the
182*cdf0e10cSrcweir unloading listeners in order to give them a chance to do cleanup and get
183*cdf0e10cSrcweir their threads in a safe state. Then all registered modules are asked if they
184*cdf0e10cSrcweir can be unloaded. That is, the function calls component_canUnload on every
185*cdf0e10cSrcweir registered module. If <code>sal_True</code> is returned then <code>osl_unloadModule</code>
186*cdf0e10cSrcweir is called for the belonging module as often as it is registered.
187*cdf0e10cSrcweir <p>
188*cdf0e10cSrcweir A call to <code>osl_unloadModule</code> does not guarantee that the module is unloaded even
189*cdf0e10cSrcweir if its <code>component_canUnload</code> function returns <code>sal_True</code>.
190*cdf0e10cSrcweir <p>
191*cdf0e10cSrcweir The optional in-parameter <code>libUnused</code> specifies a period of time which a library
192*cdf0e10cSrcweir must be unused in order to qualify for being unloaded. By using this argument
193*cdf0e10cSrcweir one can counter the multithreading problem as described further above. It is in
194*cdf0e10cSrcweir the responsibility of the user of this function to provide a timespan big enough
195*cdf0e10cSrcweir to ensure that all threads are out of modules (see <code>component_canUnload</code>).
196*cdf0e10cSrcweir <p>
197*cdf0e10cSrcweir The service managers which have been created by functions such as
198*cdf0e10cSrcweir <code>createRegistryServiceFactory</code> (declared in cppuhelper/servicefactory.hxx) are
199*cdf0e10cSrcweir registered listeners and release the references to factories on notification.
200*cdf0e10cSrcweir 
201*cdf0e10cSrcweir 
202*cdf0e10cSrcweir @param libUnused span of time that a module must be unused to be unloaded. the
203*cdf0e10cSrcweir argument is optional.
204*cdf0e10cSrcweir */
205*cdf0e10cSrcweir void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused);
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir /**
208*cdf0e10cSrcweir rtl_addUnloadingListener takes an argument of this type.
209*cdf0e10cSrcweir 
210*cdf0e10cSrcweir @param id - The value that has been passed as second argument to rtl_addUnloadingListener
211*cdf0e10cSrcweir */
212*cdf0e10cSrcweir typedef void (SAL_CALL *rtl_unloadingListenerFunc)(void* id);
213*cdf0e10cSrcweir /**
214*cdf0e10cSrcweir The function registered an unloading listener. The callback argument is a
215*cdf0e10cSrcweir function which is called  when the unloading procedure has been initiated by a call to
216*cdf0e10cSrcweir <code>rtl_unloadUnusedLibraries</code>. The second argument is used to distinguish between different
217*cdf0e10cSrcweir listener instances and may be <code>NULL</code>. It will be passed as argument when the callback
218*cdf0e10cSrcweir function is being called. The return value identifies the registered listener and will
219*cdf0e10cSrcweir be used for removing the listener later on. If the same listener is added more then
220*cdf0e10cSrcweir once then every registration is treated as if made for a different listener. That is,
221*cdf0e10cSrcweir a different cookie is returned and the callback function will be called as many times
222*cdf0e10cSrcweir as it has been registered.
223*cdf0e10cSrcweir @param callback - a function that is called to notify listeners.
224*cdf0e10cSrcweir @param this  - a value to distinguish different listener instances
225*cdf0e10cSrcweir @return identifier which is used in rtl_removeUnloadingListener
226*cdf0e10cSrcweir */
227*cdf0e10cSrcweir sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this);
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir /**
230*cdf0e10cSrcweir Listeners (the callback functions) must be unregistered before the listener code
231*cdf0e10cSrcweir becomes invalid. That is, if a module contains listener code, namely callback
232*cdf0e10cSrcweir functions of type <code>rtl_unloadingListenerFunc</code>, then those functions must not be
233*cdf0e10cSrcweir registered when <code>component_canUnload</code> returns <code>sal_True</code>.
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir @param cookie is an identifier as returned by <code>rtl_addUnloadingListener</code> function.
236*cdf0e10cSrcweir */
237*cdf0e10cSrcweir void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie );
238*cdf0e10cSrcweir 
239*cdf0e10cSrcweir 
240*cdf0e10cSrcweir /**
241*cdf0e10cSrcweir Pointers to <code>rtl_ModuleCount</code> are passed as arguments to the default factory creator
242*cdf0e10cSrcweir functions: <code>createSingleComponentFactory</code>, <code>createSingleFactory</code>,
243*cdf0e10cSrcweir <code>createOneInstanceFactory</code>.
244*cdf0e10cSrcweir The factory implementation is calling <code>rtl_ModuleCount.acquire</code> when it is being
245*cdf0e10cSrcweir constructed and it is calling <code>rtl_ModuleCount.release</code>. The implementations of
246*cdf0e10cSrcweir <code>acquire</code>
247*cdf0e10cSrcweir and <code>release</code> should influence the return value of <code>component_canUnload</code>
248*cdf0e10cSrcweir in a way that it
249*cdf0e10cSrcweir returns <code>sal_False</code> after <code>acquire</code> has been called. That is the module will not be unloaded
250*cdf0e10cSrcweir once a default factory has been created. A call to <code>release</code> may cause
251*cdf0e10cSrcweir <code>component_canUnload</code> to return <code>sal_False</code>, but only if there are
252*cdf0e10cSrcweir no object alive which
253*cdf0e10cSrcweir originated from the module. These objects are factory instances and the service instances
254*cdf0e10cSrcweir which have been created by these factories.
255*cdf0e10cSrcweir <p>
256*cdf0e10cSrcweir It is not necessary to synchronize <code>acquire</code> and <code>release</code> as a whole.
257*cdf0e10cSrcweir Simply sychronize the
258*cdf0e10cSrcweir access to a counter variable, e.g. the <code>rtl_moduleCount_release</code> implementation:
259*cdf0e10cSrcweir <pre>
260*cdf0e10cSrcweir extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that )
261*cdf0e10cSrcweir {
262*cdf0e10cSrcweir 	rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
263*cdf0e10cSrcweir 	osl_incrementInterlockedCount( &pMod->counter);
264*cdf0e10cSrcweir }
265*cdf0e10cSrcweir </pre>
266*cdf0e10cSrcweir The SAL library offers functions that can be used for <code>acquire</code> and <code>release</code>. See struct
267*cdf0e10cSrcweir <code>_rtl_StandardModuleCount</code>.
268*cdf0e10cSrcweir */
269*cdf0e10cSrcweir typedef struct _rtl_ModuleCount
270*cdf0e10cSrcweir {
271*cdf0e10cSrcweir 	void ( SAL_CALL * acquire ) ( struct _rtl_ModuleCount * that );
272*cdf0e10cSrcweir 	void ( SAL_CALL * release ) ( struct _rtl_ModuleCount * that );
273*cdf0e10cSrcweir }rtl_ModuleCount;
274*cdf0e10cSrcweir 
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir #define MODULE_COUNT_INIT \
277*cdf0e10cSrcweir { {rtl_moduleCount_acquire,rtl_moduleCount_release}, rtl_moduleCount_canUnload, 0, {0, 0}}
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir /**
280*cdf0e10cSrcweir This struct can be used to implement the unloading mechanism. To make a UNO library
281*cdf0e10cSrcweir unloadable create one global instance of this struct in the module. To initialize it one
282*cdf0e10cSrcweir uses the MODULE_COUNT_INIT macro.
283*cdf0e10cSrcweir 
284*cdf0e10cSrcweir <pre>rtl_StandardModuleCount globalModuleCount= MODULE_COUNT_INIT</pre>;
285*cdf0e10cSrcweir */
286*cdf0e10cSrcweir typedef struct _rtl_StandardModuleCount
287*cdf0e10cSrcweir {
288*cdf0e10cSrcweir 	rtl_ModuleCount modCnt;
289*cdf0e10cSrcweir  	sal_Bool (	*canUnload ) ( struct _rtl_StandardModuleCount* a, TimeValue* libUnused);
290*cdf0e10cSrcweir 	oslInterlockedCount counter;
291*cdf0e10cSrcweir 	TimeValue unusedSince;
292*cdf0e10cSrcweir } rtl_StandardModuleCount;
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir /** Default implementation for <code>rtl_ModuleCount.acquire</code>. Use this function along with
295*cdf0e10cSrcweir <code>rtl_StandardModuleCount</code>.
296*cdf0e10cSrcweir */
297*cdf0e10cSrcweir void rtl_moduleCount_acquire(rtl_ModuleCount * that );
298*cdf0e10cSrcweir /** Default implementation for <code>rtl_ModuleCount.release</code>.
299*cdf0e10cSrcweir Use this function along with
300*cdf0e10cSrcweir <code>rtl_StandardModuleCount</code>.
301*cdf0e10cSrcweir */
302*cdf0e10cSrcweir void rtl_moduleCount_release( rtl_ModuleCount * that );
303*cdf0e10cSrcweir 
304*cdf0e10cSrcweir /** Default implementation for <code>component_canUnload</code>. Use this function along with
305*cdf0e10cSrcweir <code>rtl_StandardModuleCount</code>.
306*cdf0e10cSrcweir */
307*cdf0e10cSrcweir sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue* libUnused);
308*cdf0e10cSrcweir 
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir #ifdef __cplusplus
311*cdf0e10cSrcweir }
312*cdf0e10cSrcweir #endif
313*cdf0e10cSrcweir 
314*cdf0e10cSrcweir 
315*cdf0e10cSrcweir #endif
316