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 "loaded" 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 "unaware" 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