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