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