summaryrefslogtreecommitdiff
path: root/framework/source/fwi/threadhelp/lockhelper.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'framework/source/fwi/threadhelp/lockhelper.cxx')
-rw-r--r--framework/source/fwi/threadhelp/lockhelper.cxx549
1 files changed, 549 insertions, 0 deletions
diff --git a/framework/source/fwi/threadhelp/lockhelper.cxx b/framework/source/fwi/threadhelp/lockhelper.cxx
new file mode 100644
index 000000000000..4c5ebb7a5d91
--- /dev/null
+++ b/framework/source/fwi/threadhelp/lockhelper.cxx
@@ -0,0 +1,549 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_framework.hxx"
+
+//_________________________________________________________________________________________________________________
+// my own includes
+//_________________________________________________________________________________________________________________
+#include <threadhelp/lockhelper.hxx>
+#include <general.h>
+#include <macros/debug.hxx>
+
+#include <macros/generic.hxx>
+
+//_________________________________________________________________________________________________________________
+// interface includes
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// other includes
+//_________________________________________________________________________________________________________________
+#include <vos/process.hxx>
+
+//_________________________________________________________________________________________________________________
+// namespace
+//_________________________________________________________________________________________________________________
+
+namespace framework{
+
+//_________________________________________________________________________________________________________________
+// const
+//_________________________________________________________________________________________________________________
+
+//_________________________________________________________________________________________________________________
+// declarations
+//_________________________________________________________________________________________________________________
+
+/*-************************************************************************************************************//**
+ @short use ctor to initialize instance
+ @descr We must initialize our member "m_eLockType". This value specify handling of locking.
+ User use this helper as parameter for a guard creation.
+ These guard use "m_eLockType" to set lock in the right way by using right mutex or rw-lock.
+
+ @seealso enum ELockType
+ @seealso class ReadGuard
+ @seealso class WriteGuard
+
+ @param "rSolarMutex", for some components we must be "vcl-free"! So we can't work with our solar mutex
+ directly. User must set his reference at this instance - so we can work with it!
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+LockHelper::LockHelper( ::vos::IMutex* pSolarMutex )
+ : m_pFairRWLock ( NULL )
+ , m_pOwnMutex ( NULL )
+ , m_pSolarMutex ( NULL )
+ , m_pShareableOslMutex( NULL )
+ , m_bDummySolarMutex ( sal_False )
+{
+ m_eLockType = implts_getLockType();
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex = new ::osl::Mutex;
+ }
+ break;
+ case E_SOLARMUTEX : {
+ if( pSolarMutex == NULL )
+ {
+ m_pSolarMutex = new ::vos::OMutex;
+ m_bDummySolarMutex = sal_True;
+ }
+ else
+ {
+ m_pSolarMutex = pSolarMutex;
+ }
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock = new FairRWLock;
+ }
+ break;
+ #ifdef ENABLE_ASSERTIONS
+ default : LOG_ASSERT2( m_eLockType!=E_NOTHING, "LockHelper::ctor()", "Invalid lock type found .. so code will not be threadsafe!" )
+ #endif
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short default dtor to release safed pointer
+ @descr We have created dynamical mutex- or lock-member ... or we hold a pointer to external objects.
+ We must release it!
+
+ @seealso ctor()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+LockHelper::~LockHelper()
+{
+ if( m_pShareableOslMutex != NULL )
+ {
+ // Sometimes we hold two pointer to same object!
+ // (e.g. if m_eLockType==E_OWNMUTEX!)
+ // So we should forget it ... but don't delete it twice!
+ if( m_pShareableOslMutex != m_pOwnMutex )
+ {
+ delete m_pShareableOslMutex;
+ }
+ m_pShareableOslMutex = NULL;
+ }
+ if( m_pOwnMutex != NULL )
+ {
+ delete m_pOwnMutex;
+ m_pOwnMutex = NULL;
+ }
+ if( m_pSolarMutex != NULL )
+ {
+ if (m_bDummySolarMutex)
+ {
+ delete static_cast<vos::OMutex*>(m_pSolarMutex);
+ m_bDummySolarMutex = sal_False;
+ }
+ m_pSolarMutex = NULL;
+ }
+ if( m_pFairRWLock != NULL )
+ {
+ delete m_pFairRWLock;
+ m_pFairRWLock = NULL;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IMutex
+ @short set an exclusiv lock
+ @descr We must match this lock call with current set lock type and used lock member.
+ If a mutex should be used - it will be easy ... but if a rw-lock should be used
+ we must simulate it as a write access!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method acquireWriteAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::acquire()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->acquire();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->acquire();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->acquireWriteAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IMutex
+ @short release exclusiv lock
+ @descr We must match this unlock call with current set lock type and used lock member.
+ If a mutex should be used - it will be easy ... but if a rw-lock should be used
+ we must simulate it as a write access!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method releaseWriteAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::release()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->release();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->release();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->releaseWriteAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IRWLock
+ @short set lock for reading
+ @descr A guard should call this method to acquire read access on your member.
+ Writing isn't allowed then - but nobody could check it for you!
+ We use m_eLockType to differ between all possible "lock-member"!!!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method releaseReadAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::acquireReadAccess()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->acquire();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->acquire();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->acquireReadAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IRWLock
+ @short reset lock for reading
+ @descr A guard should call this method to release read access on your member.
+ We use m_eLockType to differ between all possible "lock-member"!!!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method acquireReadAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::releaseReadAccess()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->release();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->release();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->releaseReadAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IRWLock
+ @short set lock for writing
+ @descr A guard should call this method to acquire write access on your member.
+ Reading is allowed too - of course.
+ After successfully calling of this method you are the only writer.
+ We use m_eLockType to differ between all possible "lock-member"!!!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method releaseWriteAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::acquireWriteAccess()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->acquire();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->acquire();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->acquireWriteAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IRWLock
+ @short reset lock for writing
+ @descr A guard should call this method to release write access on your member.
+ We use m_eLockType to differ between all possible "lock-member"!!!
+
+ @attention If a shareable osl mutex exist, he must be used as twice!
+ It's neccessary for some cppu-helper classes ...
+
+ @seealso method acquireWriteAccess()
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::releaseWriteAccess()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : {
+ m_pOwnMutex->release();
+ }
+ break;
+ case E_SOLARMUTEX : {
+ m_pSolarMutex->release();
+ }
+ break;
+ case E_FAIRRWLOCK : {
+ m_pFairRWLock->releaseWriteAccess();
+ }
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @interface IRWLock
+ @short downgrade a write access to a read access
+ @descr A guard should call this method to change a write to a read access.
+ New readers can work too - new writer are blocked!
+ We use m_eLockType to differ between all possible "lock-member"!!!
+
+ @attention Ignore shareable mutex(!) - because this call never should release a lock completly!
+ We change a write access to a read access only.
+
+ @attention a) Don't call this method if you are not a writer!
+ Results are not defined then ...
+ An upgrade can't be implemented realy ... because acquiring new access
+ will be the same - there no differences!
+ b) Without function if m_eLockTyp is different from E_FAIRRWLOCK(!) ...
+ because, a mutex don't support it realy.
+
+ @seealso -
+
+ @param -
+ @return -
+
+ @onerror -
+*//*-*************************************************************************************************************/
+void LockHelper::downgradeWriteAccess()
+{
+ switch( m_eLockType )
+ {
+ case E_NOTHING : break; // There is nothing to do ...
+ case E_OWNMUTEX : break; // Not supported for mutex!
+ case E_SOLARMUTEX : break; // Not supported for mutex!
+ case E_FAIRRWLOCK : m_pFairRWLock->downgradeWriteAccess();
+ break;
+ }
+}
+
+/*-************************************************************************************************************//**
+ @short return a reference to a static lock helper
+ @descr Sometimes we need the global mutex or rw-lock! (e.g. in our own static methods)
+ But it's not a good idea to use these global one very often ...
+ Thats why we use this little helper method.
+ We create our own "class global static" lock.
+ It will be created at first call only!
+ All other requests use these created one then directly.
+
+ @seealso -
+
+ @param -
+ @return A reference to a static mutex/lock member.
+
+ @onerror No error should occure.
+*//*-*************************************************************************************************************/
+LockHelper& LockHelper::getGlobalLock( ::vos::IMutex* pSolarMutex )
+{
+ // Initialize static "member" only for one time!
+ // Algorithm:
+ // a) Start with an invalid lock (NULL pointer)
+ // b) If these method first called (lock not already exist!) ...
+ // c) ... we must create a new one. Protect follow code with the global mutex -
+ // (It must be - we create a static variable!)
+ // d) Check pointer again - because ... another instance of our class could be faster then these one!
+ // e) Create the new lock and set it for return on static variable.
+ // f) Return new created or already existing lock object.
+ static LockHelper* pLock = NULL;
+ if( pLock == NULL )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if( pLock == NULL )
+ {
+ static LockHelper aLock( pSolarMutex );
+ pLock = &aLock;
+ }
+ }
+ return *pLock;
+}
+
+/*-************************************************************************************************************//**
+ @short return a reference to shared mutex member
+ @descr Sometimes we need a osl-mutex for sharing with our uno helper ...
+ What can we do?
+ a) If we have an initialized "own mutex" ... we can use it!
+ b) Otherwhise we must use a different mutex member :-(
+ I HOPE IT WORKS!
+
+ @seealso -
+
+ @param -
+ @return A reference to a shared mutex.
+
+ @onerror No error should occure.
+*//*-*************************************************************************************************************/
+::osl::Mutex& LockHelper::getShareableOslMutex()
+{
+ if( m_pShareableOslMutex == NULL )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if( m_pShareableOslMutex == NULL )
+ {
+ switch( m_eLockType )
+ {
+ case E_OWNMUTEX : {
+ m_pShareableOslMutex = m_pOwnMutex;
+ }
+ break;
+ default : {
+ m_pShareableOslMutex = new ::osl::Mutex;
+ }
+ break;
+ }
+ }
+ }
+ return *m_pShareableOslMutex;
+}
+
+/*-************************************************************************************************************//**
+ @short search for right lock type, which should be used by an instance of this struct
+ @descr We must initialize our member "m_eLockType". This value specify handling of locking.
+ How we can do that? We search for an environment variable. We do it only for one time ....
+ because the environment is fix. So we safe this value and use it for all further requests.
+ If no variable could be found - we use a fallback!
+
+ @attention We have numbered all our enum values for ELockType. So we can use it as value of searched
+ environment variable too!
+
+ @seealso enum ELockType
+ @seealso environment LOCKTYPE
+
+ @param -
+ @return A reference to a created and right initialized lock type!
+
+ @onerror We use a fallback!
+*//*-*************************************************************************************************************/
+ELockType& LockHelper::implts_getLockType()
+{
+ // Initialize static "member" only for one time!
+ // Algorithm:
+ // a) Start with an invalid variable (NULL pointer)
+ // b) If these method first called (value not already exist!) ...
+ // c) ... we must create a new one. Protect follow code with the global mutex -
+ // (It must be - we create a static variable!)
+ // d) Check pointer again - because ... another instance of our class could be faster then these one!
+ // e) Create the new static variable, get value from the environment and set it
+ // f) Return new created or already existing static variable.
+ static ELockType* pType = NULL;
+ if( pType == NULL )
+ {
+ ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
+ if( pType == NULL )
+ {
+ static ELockType eType = FALLBACK_LOCKTYPE;
+
+ ::vos::OStartupInfo aEnvironment;
+ ::rtl::OUString sValue ;
+ if( aEnvironment.getEnvironment( ENVVAR_LOCKTYPE, sValue ) == ::vos::OStartupInfo::E_None )
+ {
+ eType = (ELockType)(sValue.toInt32());
+ }
+
+ LOG_LOCKTYPE( FALLBACK_LOCKTYPE, eType )
+
+ pType = &eType;
+ }
+ }
+ return *pType;
+}
+
+} // namespace framework