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