summaryrefslogtreecommitdiff
path: root/sal/inc/rtl/unload.h
diff options
context:
space:
mode:
authorJoachim Lingner <jl@openoffice.org>2001-06-15 09:14:08 +0000
committerJoachim Lingner <jl@openoffice.org>2001-06-15 09:14:08 +0000
commitbb1bcab227b3f5d3ffa4bf06ac8066a885d6c549 (patch)
treec1b7a86866ec2d7817faa2e8ff42fb4da1e96594 /sal/inc/rtl/unload.h
parent9200539fc4416bf51e738b99603c86a922512dc6 (diff)
#67468# docu added
Diffstat (limited to 'sal/inc/rtl/unload.h')
-rw-r--r--sal/inc/rtl/unload.h224
1 files changed, 220 insertions, 4 deletions
diff --git a/sal/inc/rtl/unload.h b/sal/inc/rtl/unload.h
index f05143352f4a..a80f6fc79c04 100644
--- a/sal/inc/rtl/unload.h
+++ b/sal/inc/rtl/unload.h
@@ -2,9 +2,9 @@
*
* $RCSfile: unload.h,v $
*
- * $Revision: 1.2 $
+ * $Revision: 1.3 $
*
- * last change: $Author: jl $ $Date: 2001-06-07 09:18:08 $
+ * last change: $Author: jl $ $Date: 2001-06-15 10:14:08 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -75,6 +75,73 @@
#endif
+/** @name General
+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
+
+<ul>
+<li>An instance is still referenced </li>
+<li>A module has been loaded without registering it </li>
+<li>The service manager has created a one instance service </li>
+<li>A service instance has been added to an UNO context </li>
+</ul>
+
+<b>Notification Mechanism</b>
+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.<p>
+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 to say, 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.
+<p> 
+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.
+<p>
+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.
+
+*/
+
+
+/**
+A library which supports unloading has to implement and export a function
+called component_canUnload. <p>
+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.<p>
+
+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. <p>
+
+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.<p>
+
+component_canUnload is implicitly called by rtl_unloadUnusedModules.
+There is no need to call the function directly.
+*/
#define COMPONENT_CANUNLOAD "component_canUnload"
typedef sal_Bool (SAL_CALL * component_canUnloadFunc)( TimeValue* pTime);
@@ -86,16 +153,148 @@ extern "C"
{
#endif
+/**
+By registering a module, one declares that a module supports the
+unloading mechanism. One registers a module by calling this function.<p>
+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. <p>
+
+A module must be registered every time it has been loaded otherwise the
+unloading mechanism is not effective.<p>
+
+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.<p>
+Loading and registering have to be in this order:<br>
+load a library (osl_loadModule)<br>
+get the component_getFactory function and get a factory<br>
+register the module (rtl_registerModuleForUnloading<br>
+<p>
+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.
+
+@param module a module handle as is obtained by osl_loadModule
+@return sal_True - the module could be registered for unloading, sal_False otherwise
+*/
sal_Bool SAL_CALL rtl_registerModuleForUnloading( 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.
+<p>
+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.
+
+@param module a module handle as is obtained by osl_loadModule
+*/
void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module);
+/**
+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.
+<p> 
+A call to osl_unloadModule does not guarantee that the module is unloaded even
+if its component_canUnload function returns sal_True. 
+<p>
+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).
+<p>
+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.
+Some factories are treated differently, see paragraph about one-instance-services.
+
+@param libUnused span of time that a module must be unused to be unloaded. the
+ argument is optional.   
+*/
void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused);
+/**
+rtl_addUnloadingListener takes an argument of this type.
+
+@param id - The value that has been passed as second argument to rtl_addUnloadingListener
+*/
typedef void (SAL_CALL *rtl_unloadingListenerFunc)(void* id);
+/**
+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.
+@param callback - a function that is called to notify listeners.
+@param this - a value to distinguish different listener instances
+@return identifier which is used in rtl_removeUnloadingListener
+*/
sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this);
-void SAL_CALL 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.
+
+@param cookie is an identifier as returned by rtl_addUnloadingListener function.   
+*/
+void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie );
+/**
+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 implementation 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.
+<p>
+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:
+<pre>
+extern "C" void rtl_moduleCount_acquire(rtl_ModuleCount * that )
+{
+ rtl_StandardModuleCount* pMod= (rtl_StandardModuleCount*)that;
+ osl_incrementInterlockedCount( &pMod->counter);
+}
+</pre>
+The SAL library offers functions that can be used for acquire and release. See struct
+_rtl_StandardModuleCount.
+*/
typedef struct _rtl_ModuleCount
{
void ( SAL_CALL * acquire ) ( struct _rtl_ModuleCount * that );
@@ -106,6 +305,13 @@ typedef struct _rtl_ModuleCount
#define MODULE_COUNT_INIT \
{ {rtl_moduleCount_acquire,rtl_moduleCount_release}, rtl_moduleCount_canUnload, 0, {0, 0}};
+/**
+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 struct _rtl_StandardModuleCount
{
rtl_ModuleCount modCnt;
@@ -114,9 +320,19 @@ typedef struct _rtl_StandardModuleCount
TimeValue unusedSince;
} rtl_StandardModuleCount;
-
+/* Default implementation for rtl_ModuleCount.acquire. Use this function along with
+rtl_StandardModuleCount.
+*/
void rtl_moduleCount_acquire(rtl_ModuleCount * that );
+/* Default implementation for rtl_ModuleCount.release.
+Use this function along with
+rtl_StandardModuleCount.
+*/
void rtl_moduleCount_release( rtl_ModuleCount * that );
+
+/* Default implementation for component_canUnload.Use this function along with
+rtl_StandardModuleCount.
+*/
sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue* libUnused);