UDK 3.2.7 C/C++ API Reference
|
The API enables an effective way of unloading libraries in a centralized way. More...
Go to the source code of this file.
Classes | |
struct | _rtl_ModuleCount |
Pointers to rtl_ModuleCount are passed as arguments to the default factory creator functions: createSingleComponentFactory , createSingleFactory , createOneInstanceFactory . More... | |
struct | _rtl_StandardModuleCount |
This struct can be used to implement the unloading mechanism. More... | |
Defines | |
#define | COMPONENT_CANUNLOAD "component_canUnload" |
A library which supports unloading has to implement and export a function called component_canUnload . | |
#define | MODULE_COUNT_INIT { {rtl_moduleCount_acquire,rtl_moduleCount_release}, rtl_moduleCount_canUnload, 0, {0, 0}} |
Typedefs | |
typedef sal_Bool(* | component_canUnloadFunc )(TimeValue *pTime) |
typedef void(* | rtl_unloadingListenerFunc )(void *id) |
rtl_addUnloadingListener takes an argument of this type. | |
typedef struct _rtl_ModuleCount | rtl_ModuleCount |
Pointers to rtl_ModuleCount are passed as arguments to the default factory creator functions: createSingleComponentFactory , createSingleFactory , createOneInstanceFactory . | |
typedef struct _rtl_StandardModuleCount | rtl_StandardModuleCount |
This struct can be used to implement the unloading mechanism. | |
Functions | |
SAL_DLLPUBLIC sal_Bool | rtl_registerModuleForUnloading (oslModule module) |
C-interface for a module reference counting. | |
SAL_DLLPUBLIC void | rtl_unregisterModuleForUnloading (oslModule module) |
The function revokes the registration of a module. | |
SAL_DLLPUBLIC void | rtl_unloadUnusedModules (TimeValue *libUnused) |
This function sets off the unloading mechanism. | |
SAL_DLLPUBLIC sal_Int32 | rtl_addUnloadingListener (rtl_unloadingListenerFunc callback, void *_this) |
The function registered an unloading listener. | |
SAL_DLLPUBLIC void | rtl_removeUnloadingListener (sal_Int32 cookie) |
Listeners (the callback functions) must be unregistered before the listener code becomes invalid. | |
SAL_DLLPUBLIC void | rtl_moduleCount_acquire (rtl_ModuleCount *that) |
Default implementation for rtl_ModuleCount.acquire . | |
SAL_DLLPUBLIC void | rtl_moduleCount_release (rtl_ModuleCount *that) |
Default implementation for rtl_ModuleCount.release . | |
SAL_DLLPUBLIC sal_Bool | rtl_moduleCount_canUnload (rtl_StandardModuleCount *that, TimeValue *libUnused) |
Default implementation for component_canUnload . |
The API enables an effective way of unloading libraries in a centralized way.
The mechanism ensures that used libraries are not unloaded. This prevents crashes if library code is being used after unloading the library. The unloading mechanism currently only works with libraries which contain UNO services. A library cannot be unloaded if one of the following conditions apply
Notification Mechanism The API provides a notification mechanism. Clients can use it to do clean up, such as releasing cached references, in order to allow modules to be unloaded. As long as someone holds a reference to an object whose housing module supports unloading the module cannot be unloaded.
Because of the inherent danger of crashing the application by using this API all instances which control threads should be registered listeners. On notification they have to ensure that their threads assume a safe state, that is, they run outside of modules which could be unloaded and do not jump back into module code as a result of a finished function call. In other words, there must not be an address of the module on the thread's stack.
Since current operating systems lack APIs in respect to controlling the position of threads within libraries, it would be a major effort to comply with that recommendation. The best and most efficient way of handling the unloading scenario is to let all threads, except for the main thread, die in case of a notification.
Use this API with great care because it might crash the application. See the respective documentation (Library Unloading) on the udk.openoffice.org web site.
#define COMPONENT_CANUNLOAD "component_canUnload" |
A library which supports unloading has to implement and export a function called component_canUnload
.
If the function returns sal_True
then the module can be safely unloaded. That is the case when there are no external references to code within the library. In case a module houses UNO components then the function must return sal_False
after the first factory has been handed out. The function then continues to return sal_False
as long as there is at least one object (factory or service instance) which originated from the module.
Libraries which not only contain UNO components (or none at all) have to provide a means to control whether they can be unloaded or not, e.g. However, there is no concept yet.
The argument pTime
is an optional out-parameter. If the return value is sal_True
then pTime
reflects a point in time since when the module could have been unloaded. Since that time the function would have continually returned sal_True
up to the present. The value of pTime
is important for the decision as to a module will be unloaded. When someone initiates the unloading of modules by calling rtl_unloadUnusedModules
then the caller can specify a time span with the effect that only those modules are unloaded which are unused at least for that amount of time. If component_canUnload
does not fill in pTime
then the module is unloaded immediately.
component_canUnload
is implicitly called by rtl_unloadUnusedModules
. There is no need to call the function directly.
#define MODULE_COUNT_INIT { {rtl_moduleCount_acquire,rtl_moduleCount_release}, rtl_moduleCount_canUnload, 0, {0, 0}} |
typedef sal_Bool( * component_canUnloadFunc)(TimeValue *pTime) |
typedef struct _rtl_ModuleCount rtl_ModuleCount |
Pointers to rtl_ModuleCount
are passed as arguments to the default factory creator functions: createSingleComponentFactory
, createSingleFactory
, createOneInstanceFactory
.
The factory implementation is calling rtl_ModuleCount.acquire
when it is being constructed and it is calling rtl_ModuleCount.release
. The implementations of acquire
and release
should influence the return value of component_canUnload
in a way that it returns sal_False
after acquire
has been called. That is the module will not be unloaded once a default factory has been created. A call to release
may cause component_canUnload
to return sal_False
, but only if there are no object alive which originated from the module. These objects are factory instances and the service instances which have been created by these factories.
It is not necessary to synchronize acquire
and release
as a whole. Simply sychronize the access to a counter variable, e.g. the rtl_moduleCount_release
implementation:
extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that ) { rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that; osl_incrementInterlockedCount( &pMod->counter); }
The SAL library offers functions that can be used for acquire
and release
. See struct _rtl_StandardModuleCount
.
typedef struct _rtl_StandardModuleCount rtl_StandardModuleCount |
This struct can be used to implement the unloading mechanism.
To make a UNO library unloadable create one global instance of this struct in the module. To initialize it one uses the MODULE_COUNT_INIT macro.
rtl_StandardModuleCount globalModuleCount= MODULE_COUNT_INIT
;
typedef void( * rtl_unloadingListenerFunc)(void *id) |
rtl_addUnloadingListener takes an argument of this type.
id | - The value that has been passed as second argument to rtl_addUnloadingListener |
SAL_DLLPUBLIC sal_Int32 rtl_addUnloadingListener | ( | rtl_unloadingListenerFunc | callback, |
void * | _this | ||
) |
The function registered an unloading listener.
The callback argument is a function which is called when the unloading procedure has been initiated by a call to rtl_unloadUnusedLibraries
. The second argument is used to distinguish between different listener instances and may be NULL
. It will be passed as argument when the callback function is being called. The return value identifies the registered listener and will be used for removing the listener later on. If the same listener is added more then once then every registration is treated as if made for a different listener. That is, a different cookie is returned and the callback function will be called as many times as it has been registered.
callback | - a function that is called to notify listeners. |
_this | - a value to distinguish different listener instances |
SAL_DLLPUBLIC void rtl_moduleCount_acquire | ( | rtl_ModuleCount * | that | ) |
Default implementation for rtl_ModuleCount.acquire
.
Use this function along with rtl_StandardModuleCount
.
SAL_DLLPUBLIC sal_Bool rtl_moduleCount_canUnload | ( | rtl_StandardModuleCount * | that, |
TimeValue * | libUnused | ||
) |
Default implementation for component_canUnload
.
Use this function along with rtl_StandardModuleCount
.
SAL_DLLPUBLIC void rtl_moduleCount_release | ( | rtl_ModuleCount * | that | ) |
Default implementation for rtl_ModuleCount.release
.
Use this function along with rtl_StandardModuleCount
.
C-interface for a module reference counting.
By registering a module, one declares that a module supports the unloading mechanism. One registers a module by calling this function.
A module can only be unloaded from memory when it has been registered as many times as it has been loaded. The reason is that a library can be "loaded" several times by osl_loadModule
within the same process. The function will then return the same module handle because the library will effectively only be loaded once. To remove the library from memory it is necessary to call osl_unloadModule
as often as osl_loadModule
was called. The function rtl_unloadUnusedModules
calls osl_unloadModule
for a module as many times as it was registered. If, for example, a module has been registered one time less then osl_loadModule
has been called and the module can be unloaded then it needs a call to rtl_unloadUnusedModules
and an explicit call to osl_unloadModule
to remove the module from memory.
A module must be registered every time it has been loaded otherwise the unloading mechanism is not effective.
Before a module is registered, one has to make sure that the module is in a state that prevents it from being unloaded. In other words, component_canUnload
must return sal_False
. Assuming that component_canUnload
returns sal_True
and it is registered regardless, then a call to rtl_unloadUnusedModules
causes the module to be unloaded. This unloading can be set off by a different thread and the thread which registered the module is "unaware" of this. Then when the first thread tries to obtain a factory or calls another function in the module, the application will crash, because the module has been unloaded before. Therefore one has to ensure that the module cannot be unloaded before it is registered. This is simply done by obtaining a factory from the module. As long as a factory or some other object, which has been created by the factory, is alive, the component_canUnload
function will return sal_False
.
Loading and registering have to be in this order:
osl_loadModule
) component_getFactory
function and get a factory Usually the service manager is used to obtain an instance of a service. The service manager registers all modules which support the unloading mechanism. When the service manager is used to get service instances than one does not have to bother about registering.
module | a module handle as is obtained by osl_loadModule |
SAL_DLLPUBLIC void rtl_removeUnloadingListener | ( | sal_Int32 | cookie | ) |
Listeners (the callback functions) must be unregistered before the listener code becomes invalid.
That is, if a module contains listener code, namely callback functions of type rtl_unloadingListenerFunc
, then those functions must not be registered when component_canUnload
returns sal_True
.
cookie | is an identifier as returned by rtl_addUnloadingListener function. |
SAL_DLLPUBLIC void rtl_unloadUnusedModules | ( | TimeValue * | libUnused | ) |
This function sets off the unloading mechanism.
At first it notifies the unloading listeners in order to give them a chance to do cleanup and get their threads in a safe state. Then all registered modules are asked if they can be unloaded. That is, the function calls component_canUnload on every registered module. If sal_True
is returned then osl_unloadModule
is called for the belonging module as often as it is registered.
A call to osl_unloadModule
does not guarantee that the module is unloaded even if its component_canUnload
function returns sal_True
.
The optional in-parameter libUnused
specifies a period of time which a library must be unused in order to qualify for being unloaded. By using this argument one can counter the multithreading problem as described further above. It is in the responsibility of the user of this function to provide a timespan big enough to ensure that all threads are out of modules (see component_canUnload
).
The service managers which have been created by functions such as createRegistryServiceFactory
(declared in cppuhelper/servicefactory.hxx) are registered listeners and release the references to factories on notification.
libUnused | span of time that a module must be unused to be unloaded. the argument is optional. |
SAL_DLLPUBLIC void rtl_unregisterModuleForUnloading | ( | oslModule | module | ) |
The function revokes the registration of a module.
By calling the function for a previously registered module one prevents the module from being unloaded by this unloading mechanism. However, in order to completely unregister the module it is necessary to call the function as often as the module has been registered.
rtl_unloadUnusedModules
unregisters the modules which it unloads. Therefore there is no need to call this function unless one means to prevent the unloading of a module.
module | a module handle as is obtained by osl_loadModule |