[PATCH] API CHANGE: remove some of useless rtl/unload.h functionalit...
Matúš Kukan (via_Code_Review)
gerrit at gerrit.libreoffice.org
Wed Apr 10 12:36:49 PDT 2013
Hi,
I have submitted a patch for review:
https://gerrit.libreoffice.org/3317
To pull it, you can do:
git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/17/3317/1
API CHANGE: remove some of useless rtl/unload.h functionality
Change-Id: If32923e35ef97f42d5203975362e5c76948ff327
---
M sal/inc/rtl/unload.h
M sal/osl/all/compat.cxx
M sal/rtl/unload.cxx
3 files changed, 23 insertions(+), 551 deletions(-)
diff --git a/sal/inc/rtl/unload.h b/sal/inc/rtl/unload.h
index 9de17b4..0bbc414 100644
--- a/sal/inc/rtl/unload.h
+++ b/sal/inc/rtl/unload.h
@@ -27,209 +27,12 @@
#include "sal/saldllapi.h"
#include "sal/types.h"
-/** @file
-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, 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 <code>component_canUnload</code>. <p>
-If the function returns <code>sal_True</code> 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
-<code>sal_False</code> after the first factory has been handed out. The function then
-continues to return <code>sal_False</code> 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 <code>pTime</code> is an optional out-parameter. If the return value is
-<code>sal_True</code> then <code>pTime</code> reflects a point in time since
-when the module could have
-been unloaded. Since that time the function would have continually returned
-<code>sal_True</code> up to the present. The value of <code>pTime</code> is
-important for the decision
-as to a module will be unloaded. When someone initiates the unloading of
-modules by calling <code>rtl_unloadUnusedModules</code> 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 <code>component_canUnload</code> does not
-fill in <code>pTime</code>
-then the module is unloaded immediately.<p>
-
-<code>component_canUnload</code> is implicitly called by <code>rtl_unloadUnusedModules
-</code>. There is no need to call the function directly.
-*/
-#define COMPONENT_CANUNLOAD "component_canUnload"
-typedef sal_Bool (SAL_CALL * component_canUnloadFunc)( TimeValue* pTime);
-
-
/** C-interface for a module reference counting
*/
#ifdef __cplusplus
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 <code>osl_loadModule</code>
-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 <code>osl_unloadModule</code> as often as <code>
-osl_loadModule</code> was called. The
-function <code>rtl_unloadUnusedModules</code> calls <code>osl_unloadModule</code>
-for a module as many
-times as it was registered. If, for example, a module has been registered one
-time less then <code>osl_loadModule</code> has been called and the module can be unloaded
-then it needs a call to <code>rtl_unloadUnusedModules</code> and an explicit call to
-<code>osl_unloadModule</code> 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,
-<code>component_canUnload</code> must return <code>sal_False</code>. Assuming that
-<code>component_canUnload</code>
-returns <code>sal_True</code> and it is registered regardless, then a call to
-<code>rtl_unloadUnusedModules</code> 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 <code>component_canUnload</code> function will
-return <code>sal_False</code>.<p>
-Loading and registering have to be in this order:<br>
-<ul>
-<li>load a library (<code>osl_loadModule</code>)</li>
-<li>get the <code>component_getFactory</code> function and get a factory</li>
-<li>register the module (rtl_registerModuleForUnloading</li>
-</ul>
-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.
-
- at param module a module handle as is obtained by osl_loadModule
- at return sal_True - the module could be registered for unloading, sal_False otherwise
-*/
-SAL_DLLPUBLIC 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>
-<code>rtl_unloadUnusedModules</code> 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.
-
- at param module a module handle as is obtained by osl_loadModule
-*/
-SAL_DLLPUBLIC 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 <code>sal_True</code> is returned then <code>osl_unloadModule</code>
-is called for the belonging module as often as it is registered.
-<p>
-A call to <code>osl_unloadModule</code> does not guarantee that the module is unloaded even
-if its <code>component_canUnload</code> function returns <code>sal_True</code>.
-<p>
-The optional in-parameter <code>libUnused</code> 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 <code>component_canUnload</code>).
-<p>
-The service managers which have been created by functions such as
-<code>createRegistryServiceFactory</code> (declared in cppuhelper/servicefactory.hxx) are
-registered listeners and release the references to factories on notification.
-
-
- at param libUnused span of time that a module must be unused to be unloaded. the
-argument is optional.
-*/
-SAL_DLLPUBLIC void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused);
-
-/**
-rtl_addUnloadingListener takes an argument of this type.
-
- at 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
-<code>rtl_unloadUnusedLibraries</code>. The second argument is used to distinguish between different
-listener instances and may be <code>NULL</code>. 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.
- at param callback - a function that is called to notify listeners.
- at param _this - a value to distinguish different listener instances
- at return identifier which is used in rtl_removeUnloadingListener
-*/
-SAL_DLLPUBLIC sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this);
-
-/**
-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 <code>rtl_unloadingListenerFunc</code>, then those functions must not be
-registered when <code>component_canUnload</code> returns <code>sal_True</code>.
-
- at param cookie is an identifier as returned by <code>rtl_addUnloadingListener</code> function.
-*/
-SAL_DLLPUBLIC void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie );
-
/**
Pointers to <code>rtl_ModuleCount</code> are passed as arguments to the default factory creator
diff --git a/sal/osl/all/compat.cxx b/sal/osl/all/compat.cxx
index f9c7129..4b64326 100644
--- a/sal/osl/all/compat.cxx
+++ b/sal/osl/all/compat.cxx
@@ -11,6 +11,8 @@
#include <cstdlib>
+#include "osl/module.h"
+#include "osl/time.h"
#include "sal/types.h"
// Stubs for removed functionality, to be killed when we bump sal SONAME
@@ -69,6 +71,27 @@
std::abort();
}
+SAL_DLLPUBLIC_EXPORT sal_Bool SAL_CALL rtl_registerModuleForUnloading(oslModule) {
+ std::abort();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_unregisterModuleForUnloading(oslModule) {
+ std::abort();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_unloadUnusedModules(TimeValue *) {
+ std::abort();
+}
+
+typedef void (SAL_CALL *rtl_unloadingListenerFunc)(void *id);
+SAL_DLLPUBLIC_EXPORT sal_Int32 SAL_CALL rtl_addUnloadingListener(rtl_unloadingListenerFunc, void *) {
+ std::abort();
+}
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL rtl_removeUnloadingListener(sal_Int32) {
+ std::abort();
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/rtl/unload.cxx b/sal/rtl/unload.cxx
index 4d4a414..8bfff77 100644
--- a/sal/rtl/unload.cxx
+++ b/sal/rtl/unload.cxx
@@ -37,72 +37,6 @@
#ifndef DISABLE_DYNLOADING
-static void rtl_notifyUnloadingListeners();
-
-static sal_Bool isEqualTimeValue ( const TimeValue* time1, const TimeValue* time2)
-{
- if( time1->Seconds == time2->Seconds &&
- time1->Nanosec == time2->Nanosec)
- return sal_True;
- else
- return sal_False;
-}
-
-static sal_Bool isGreaterTimeValue( const TimeValue* time1, const TimeValue* time2)
-{
- sal_Bool retval= sal_False;
- if ( time1->Seconds > time2->Seconds)
- retval= sal_True;
- else if ( time1->Seconds == time2->Seconds)
- {
- if( time1->Nanosec > time2->Nanosec)
- retval= sal_True;
- }
- return retval;
-}
-
-static sal_Bool isGreaterEqualTimeValue( const TimeValue* time1, const TimeValue* time2)
-{
- if( isEqualTimeValue( time1, time2) )
- return sal_True;
- else if( isGreaterTimeValue( time1, time2))
- return sal_True;
- else
- return sal_False;
-}
-
-static void addTimeValue( const TimeValue* value1, const TimeValue* value2, TimeValue* result)
-{
- sal_uInt64 sum;
- result->Nanosec=0;
- result->Seconds=0;
-
- sum= value1->Nanosec + value2->Nanosec;
- if( sum >= 1000000000 )
- {
- result->Seconds=1;
- sum -= 1000000000;
- }
- result->Nanosec= (sal_uInt32)sum;
- result->Seconds += value1->Seconds + value2->Seconds;
-}
-
-
-static sal_Bool hasEnoughTimePassed( const TimeValue* unusedSince, const TimeValue* timespan)
-{
- sal_Bool retval= sal_False;
- TimeValue currentTime;
- if( osl_getSystemTime( ¤tTime))
- {
- TimeValue addedTime;
- addTimeValue( unusedSince, timespan, &addedTime);
- if( isGreaterEqualTimeValue( ¤tTime, &addedTime))
- retval= sal_True;
- }
-
- return retval;
-}
-
namespace
{
class theUnloadingMutex : public rtl::Static<osl::Mutex, theUnloadingMutex>{};
@@ -147,43 +81,6 @@
#endif
}
-#ifndef DISABLE_DYNLOADING
-
-struct hashModule
-{
- size_t operator()( const oslModule& rkey) const
- {
- return (size_t)rkey;
- }
-};
-
-typedef boost::unordered_map<
- oslModule,
- std::pair<sal_uInt32, component_canUnloadFunc>,
- hashModule,
- std::equal_to<oslModule>,
- rtl::Allocator<oslModule>
-> ModuleMap;
-
-typedef ModuleMap::iterator Mod_IT;
-
-static ModuleMap& getModuleMap()
-{
- static ModuleMap * g_pMap= NULL;
- if (!g_pMap)
- {
- MutexGuard guard( getUnloadingMutex() );
- if (!g_pMap)
- {
- static ModuleMap g_aModuleMap;
- g_pMap= &g_aModuleMap;
- }
- }
- return *g_pMap;
-}
-
-#endif
-
extern "C" sal_Bool rtl_moduleCount_canUnload( rtl_StandardModuleCount * that, TimeValue * libUnused)
{
#ifdef DISABLE_DYNLOADING
@@ -202,256 +99,5 @@
return (that->counter == 0);
#endif
}
-
-
-extern "C" sal_Bool SAL_CALL rtl_registerModuleForUnloading( oslModule module)
-{
-#ifdef DISABLE_DYNLOADING
- (void) module;
- return sal_False;
-#else
- MutexGuard guard( getUnloadingMutex());
- ModuleMap& moduleMap= getModuleMap();
- sal_Bool ret= sal_True;
-
- // If the module has been registered before, then find it and increment
- // its reference cout
- Mod_IT it= moduleMap.find( module);
- if( it != moduleMap.end())
- {
- //module already registered, increment ref count
- it->second.first++;
- }
- else
- {
- // Test if the module supports unloading (exports component_canUnload)
- rtl::OUString name(RTL_CONSTASCII_USTRINGPARAM( COMPONENT_CANUNLOAD));
- component_canUnloadFunc pFunc=
- (component_canUnloadFunc)osl_getFunctionSymbol( module, name.pData);
- if (pFunc)
- {
- //register module for the first time, set ref count to 1
- moduleMap[module]= std::make_pair((sal_uInt32)1, pFunc);
- }
- else
- ret= sal_False;
- }
- return ret;
-#endif
-}
-
-extern "C" void SAL_CALL rtl_unregisterModuleForUnloading( oslModule module)
-{
-#ifdef DISABLE_DYNLOADING
- (void) module;
-#else
- MutexGuard guard( getUnloadingMutex());
-
- ModuleMap& moduleMap= getModuleMap();
- Mod_IT it= moduleMap.find( module);
- if( it != moduleMap.end() )
- {
- // The module is registered, decrement ref count.
- it->second.first --;
-
- // If the refcount == 0 then remove the module from the map
- if( it->second.first == 0)
- moduleMap.erase( it);
- }
-#endif
-}
-
-extern "C" void SAL_CALL rtl_unloadUnusedModules( TimeValue* libUnused)
-{
-#ifdef DISABLE_DYNLOADING
- (void) libUnused;
-#else
- MutexGuard guard( getUnloadingMutex());
-
- typedef std::list< oslModule, rtl::Allocator<oslModule> > list_type;
- list_type unloadedModulesList;
-
- ModuleMap& moduleMap= getModuleMap();
- Mod_IT it_e= moduleMap.end();
-
- // notify all listeners
- rtl_notifyUnloadingListeners();
-
- // prepare default TimeValue if argumetn is NULL
- TimeValue nullTime={0,0};
- TimeValue* pLibUnused= libUnused? libUnused : &nullTime;
-
- Mod_IT it= moduleMap.begin();
- for (; it != it_e; ++it)
- {
- //can the module be unloaded?
- component_canUnloadFunc func= it->second.second;
- TimeValue unusedSince= {0, 0};
-
- if( func( &unusedSince) )
- {
- // module can be unloaded if it has not been used at least for the time
- // specified by the argument libUnused
- if( hasEnoughTimePassed( &unusedSince, pLibUnused))
- {
- // get the reference count and unload the module as many times
- sal_uInt32 refCount= it->second.first;
-
- for ( sal_uInt32 i=0; i < refCount; i++)
- osl_unloadModule( it->first);
-
- // mark the module for later removal
- unloadedModulesList.push_front( it->first);
- }
- }
- }
-
- // remove all entries containing invalid (unloaded) modules
- list_type::const_iterator un_it= unloadedModulesList.begin();
- for (; un_it != unloadedModulesList.end(); ++un_it)
- {
- moduleMap.erase( *un_it);
- }
-#endif
-}
-
-#ifndef DISABLE_DYNLOADING
-
-// ==============================================================================
-// Unloading Listener Administration
-//===============================================================================
-struct hashListener
-{
- size_t operator()( const sal_Int32& rkey) const
- {
- return (size_t)rkey;
- }
-};
-
-typedef boost::unordered_map<
- sal_Int32,
- std::pair<rtl_unloadingListenerFunc, void*>,
- hashListener,
- std::equal_to<sal_Int32>,
- rtl::Allocator<sal_Int32>
-> ListenerMap;
-
-typedef ListenerMap::iterator Lis_IT;
-
-static ListenerMap& getListenerMap()
-{
- static ListenerMap * g_pListeners= NULL;
- if (!g_pListeners)
- {
- MutexGuard guard( getUnloadingMutex() );
- if (!g_pListeners)
- {
- static ListenerMap g_aListenerMap;
- g_pListeners= &g_aListenerMap;
- }
- }
- return *g_pListeners;
-}
-
-
-// This queue contains cookies which have been passed out by rtl_addUnloadingListener and
-// which have been regainded by rtl_removeUnloadingListener. When rtl_addUnloadingListener
-// is called then a cookie has to be returned. First we look into the set if there is one
-// available. Otherwise a new cookie will be provided.
-// not a new value is returned.
-
-typedef std::deque<
- sal_Int32,
- rtl::Allocator<sal_Int32>
-> queue_type;
-
-static queue_type& getCookieQueue()
-{
- static queue_type * g_pCookies= NULL;
- if (!g_pCookies)
- {
- MutexGuard guard( getUnloadingMutex() );
- if (!g_pCookies)
- {
- static queue_type g_aCookieQueue;
- g_pCookies= &g_aCookieQueue;
- }
- }
- return *g_pCookies;
-}
-
-static sal_Int32 getCookie()
-{
- static sal_Int32 cookieValue= 1;
-
- sal_Int32 retval;
- queue_type& regainedCookies= getCookieQueue();
- if( regainedCookies.empty() )
- retval= cookieValue++;
- else
- {
- retval= regainedCookies.front();
- regainedCookies.pop_front();
- }
- return retval;
-}
-
-static inline void recycleCookie( sal_Int32 i)
-{
- getCookieQueue().push_back(i);
-}
-
-
-#endif
-
-// calling the function twice with the same arguments will return tow different cookies.
-// The listener will then notified twice.
-
-extern "C"
-sal_Int32 SAL_CALL rtl_addUnloadingListener( rtl_unloadingListenerFunc callback, void* _this)
-{
-#ifdef DISABLE_DYNLOADING
- (void) callback;
- (void) _this;
- return 0;
-#else
- MutexGuard guard( getUnloadingMutex());
-
- sal_Int32 cookie= getCookie();
- ListenerMap& listenerMap= getListenerMap();
- listenerMap[ cookie]= std::make_pair( callback, _this);
- return cookie;
-#endif
-}
-
-
-extern "C"
-void SAL_CALL rtl_removeUnloadingListener( sal_Int32 cookie )
-{
-#ifdef DISABLE_DYNLOADING
- (void) cookie;
-#else
- MutexGuard guard( getUnloadingMutex());
-
- ListenerMap& listenerMap= getListenerMap();
- size_t removedElements= listenerMap.erase( cookie);
- if( removedElements )
- recycleCookie( cookie);
-#endif
-}
-
-#ifndef DISABLE_DYNLOADING
-
-static void rtl_notifyUnloadingListeners()
-{
- ListenerMap& listenerMap= getListenerMap();
- for( Lis_IT it= listenerMap.begin(); it != listenerMap.end(); ++it)
- {
- rtl_unloadingListenerFunc callbackFunc= it->second.first;
- callbackFunc( it->second.second);
- }
-}
-
-#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
--
To view, visit https://gerrit.libreoffice.org/3317
To unsubscribe, visit https://gerrit.libreoffice.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: If32923e35ef97f42d5203975362e5c76948ff327
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: master
Gerrit-Owner: Matúš Kukan <matus.kukan at gmail.com>
More information about the LibreOffice
mailing list