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