diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-08-15 08:05:51 +0200 |
---|---|---|
committer | Jan-Marek Glogowski <glogow@fbihome.de> | 2017-09-19 09:25:14 +0200 |
commit | 3840aede596e6fc24f7ed7df9100fb028134aac6 (patch) | |
tree | 74d1d5efa3b2ad5448181fc185faf226aed192e4 /vcl/win | |
parent | 10b49dfb3996f99dec8dd0d2ffae2aef4022f395 (diff) |
Unify SolarMutex implementations
All backends implement the SolarMutex in mostly the same way.
So this consolidates this code into a GenericSolarMutex.
We still need the abstract SolarMutex class for the fake AKA
fascade implementation in dbaccess.
The patch also replaces various places of direct mutex usage with
either SolarMutexGuard or SolarMutexReleaser objects.
Change-Id: Ia0146dd6c51a3b9a513cc6af34a66def58aad831
Reviewed-on: https://gerrit.libreoffice.org/42325
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
Diffstat (limited to 'vcl/win')
-rw-r--r-- | vcl/win/app/salinst.cxx | 205 | ||||
-rw-r--r-- | vcl/win/gdi/salprn.cxx | 30 |
2 files changed, 81 insertions, 154 deletions
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index 97a5b6c55ad4..2f4e0b669689 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -96,99 +96,47 @@ void SalAbort( const OUString& rErrorText, bool ) LRESULT CALLBACK SalComWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); -class SalYieldMutex : public comphelper::SolarMutex +class SalYieldMutex : public comphelper::GenericSolarMutex { public: // for ImplSalYield() and ImplSalYieldMutexAcquireWithWait() - osl::Mutex m_mutex; - osl::Condition m_condition; /// for MsgWaitForMultipleObjects() - WinSalInstance* mpInstData; - sal_uLong mnCount; - DWORD mnThreadId; + osl::Condition m_condition; /// for MsgWaitForMultipleObjects() -public: - explicit SalYieldMutex( WinSalInstance* pInstData ); +protected: + virtual void doAcquire( sal_uInt32 nLockCount ) override; + virtual sal_uInt32 doRelease( bool bUnlockAll ) override; - virtual void acquire() override; - virtual void release() override; - virtual bool tryToAcquire() override; + static void BeforeReleaseHandler(); - sal_uLong GetAcquireCount( sal_uLong nThreadId ); -}; +public: + explicit SalYieldMutex(); -SalYieldMutex::SalYieldMutex( WinSalInstance* pInstData ) -{ - mpInstData = pInstData; - mnCount = 0; - mnThreadId = 0; -} + virtual bool IsCurrentThread() const override; +}; -void SalYieldMutex::acquire() +SalYieldMutex::SalYieldMutex() { - m_mutex.acquire(); - mnCount++; - mnThreadId = GetCurrentThreadId(); + SetBeforeReleaseHandler( &SalYieldMutex::BeforeReleaseHandler ); } -void SalYieldMutex::release() +void SalYieldMutex::BeforeReleaseHandler() { - DWORD nThreadId = GetCurrentThreadId(); - assert(mnThreadId == nThreadId); - - bool const isRelease(1 == mnCount); - if ( isRelease ) - { - OpenGLContext::prepareForYield(); - - SalData* pSalData = GetSalData(); - if ( pSalData->mnAppThreadId != nThreadId ) - { - // If we don't call these message, the Output from the - // Java clients doesn't come in the right order - GdiFlush(); - - } - mnThreadId = 0; - } - - mnCount--; - m_mutex.release(); - - if ( isRelease ) - { // do this *after* release - m_condition.set(); // wake up ImplSalYieldMutexAcquireWithWait() - } -} + OpenGLContext::prepareForYield(); -bool SalYieldMutex::tryToAcquire() -{ - if( m_mutex.tryToAcquire() ) + if ( GetSalData()->mnAppThreadId != GetCurrentThreadId() ) { - mnCount++; - mnThreadId = GetCurrentThreadId(); - return true; + // If we don't call these message, the Output from the + // Java clients doesn't come in the right order + GdiFlush(); } - else - return false; -} - -sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId ) -{ - if ( nThreadId == mnThreadId ) - return mnCount; - else - return 0; } /// note: while VCL is fully up and running (other threads started and /// before shutdown), the main thread must acquire SolarMutex only via /// this function to avoid deadlock -void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount ) +void SalYieldMutex::doAcquire( sal_uInt32 nLockCount ) { WinSalInstance* pInst = GetSalData()->mpFirstInstance; - if ( !pInst ) - return; - - if ( pInst->IsMainThread() ) + if ( pInst && pInst->IsMainThread() ) { // tdf#96887 If this is the main thread, then we must wait for two things: // - the mpSalYieldMutex being freed @@ -197,26 +145,41 @@ void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount ) // needed because if we don't reschedule, then we create deadlocks if a // Window's create/destroy is called via SendMessage() from another thread. // Have a look at the osl_waitCondition implementation for more info. - SalYieldMutex * const pYieldMutex = pInst->mpSalYieldMutex; - osl::Condition &rCondition = pYieldMutex->m_condition; - while ( nCount ) - { - do { - // reset condition *before* acquiring! - rCondition.reset(); - if (pYieldMutex->tryToAcquire()) - break; - // wait for SalYieldMutex::release() to set the condition - osl::Condition::Result res = rCondition.wait(); - assert(osl::Condition::Result::result_ok == res); - } - while ( true ); - --nCount; + do { + // reset condition *before* acquiring! + m_condition.reset(); + if (m_aMutex.tryToAcquire()) + break; + // wait for SalYieldMutex::release() to set the condition + osl::Condition::Result res = m_condition.wait(); + assert(osl::Condition::Result::result_ok == res); } + while ( true ); } else - // If this is not the main thread, call acquire directly. - ImplSalAcquireYieldMutex( nCount ); + m_aMutex.acquire(); + ++m_nCount; + --nLockCount; + + comphelper::GenericSolarMutex::doAcquire( nLockCount ); +} + +sal_uInt32 SalYieldMutex::doRelease( const bool bUnlockAll ) +{ + sal_uInt32 nCount = comphelper::GenericSolarMutex::doRelease( bUnlockAll ); + + // wake up ImplSalYieldMutexAcquireWithWait() after release + if ( 0 == m_nCount ) + m_condition.set(); + + return nCount; +} + +void ImplSalYieldMutexAcquireWithWait( sal_uLong nCount ) +{ + WinSalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst ) + pInst->mpSalYieldMutex->acquire( nCount ); } bool ImplSalYieldMutexTryToAcquire() @@ -238,47 +201,10 @@ void ImplSalYieldMutexRelease() } } -sal_uLong ImplSalReleaseYieldMutex() +bool SalYieldMutex::IsCurrentThread() const { - WinSalInstance* pInst = GetSalData()->mpFirstInstance; - if ( !pInst ) - return 0; - - SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; - const sal_uLong nCount = pYieldMutex->GetAcquireCount( GetCurrentThreadId() ); - sal_uLong n = nCount; - while ( n ) - { - pYieldMutex->release(); - n--; - } - - return nCount; -} - -void ImplSalAcquireYieldMutex( sal_uLong nCount ) -{ - WinSalInstance* pInst = GetSalData()->mpFirstInstance; - if ( !pInst ) - return; - - SalYieldMutex* pYieldMutex = pInst->mpSalYieldMutex; - while ( nCount ) - { - pYieldMutex->acquire(); - nCount--; - } -} - -bool WinSalInstance::CheckYieldMutex() -{ - SalData* pSalData = GetSalData(); - if ( pSalData->mpFirstInstance ) - { - SalYieldMutex* pYieldMutex = pSalData->mpFirstInstance->mpSalYieldMutex; - return (pYieldMutex->mnThreadId == (GetCurrentThreadId())); - } - return true; + // For the Windows backend, the LO identifier is the system thread ID + return m_nThreadId == GetCurrentThreadId(); } void SalData::initKeyCodeMap() @@ -520,14 +446,12 @@ void DestroySalInstance( SalInstance* pInst ) WinSalInstance::WinSalInstance() { mhComWnd = nullptr; - mpSalYieldMutex = new SalYieldMutex( this ); + mpSalYieldMutex = new SalYieldMutex(); mpSalYieldMutex->acquire(); - ::comphelper::SolarMutex::setSolarMutex( mpSalYieldMutex ); } WinSalInstance::~WinSalInstance() { - ::comphelper::SolarMutex::setSolarMutex( nullptr ); mpSalYieldMutex->release(); delete mpSalYieldMutex; DestroyWindow( mhComWnd ); @@ -538,14 +462,14 @@ comphelper::SolarMutex* WinSalInstance::GetYieldMutex() return mpSalYieldMutex; } -sal_uLong WinSalInstance::ReleaseYieldMutex() +sal_uInt32 WinSalInstance::ReleaseYieldMutex( bool bUnlockAll ) { - return ImplSalReleaseYieldMutex(); + return mpSalYieldMutex->release( bUnlockAll ); } -void WinSalInstance::AcquireYieldMutex( sal_uLong nCount ) +void WinSalInstance::AcquireYieldMutex( sal_uInt32 nCount ) { - ImplSalAcquireYieldMutex( nCount ); + mpSalYieldMutex->acquire( nCount ); } static void ImplSalDispatchMessage( MSG* pMsg ) @@ -615,8 +539,8 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong bool bDidWork = false; // NOTE: if nReleased != 0 this will be called without SolarMutex // so don't do anything dangerous before releasing it here - sal_uLong const nCount = (nReleased != 0) - ? nReleased : ImplSalReleaseYieldMutex(); + sal_uInt32 const nCount = (nReleased != 0) + ? nReleased : mpSalYieldMutex->release( true ); if ( !IsMainThread() ) { // #97739# A SendMessage call blocks until the called thread (here: the main thread) @@ -635,16 +559,13 @@ bool WinSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLong // If you change the SendMessageW function, you might need to update // the PeekMessage( ... PM_QS_POSTMESSAGE) calls! bDidWork = SendMessageW( mhComWnd, SAL_MSG_THREADYIELD, (WPARAM)bWait, (LPARAM)bHandleAllCurrentEvents ); - - ImplSalAcquireYieldMutex( nCount ); } else { if (nReleased == 0) // tdf#99383 ReAcquireSolarMutex shouldn't Yield bDidWork = ImplSalYield( bWait, bHandleAllCurrentEvents ); - - ImplSalYieldMutexAcquireWithWait( nCount ); } + mpSalYieldMutex->acquire( nCount ); return bDidWork; } diff --git a/vcl/win/gdi/salprn.cxx b/vcl/win/gdi/salprn.cxx index 365bf44c06e4..4775e804f2f9 100644 --- a/vcl/win/gdi/salprn.cxx +++ b/vcl/win/gdi/salprn.cxx @@ -396,16 +396,17 @@ static bool ImplUpdateSalJobSetup( WinSalInfoPrinter const * pPrinter, ImplJobSe } // Release mutex, in the other case we don't get paints and so on - sal_uLong nMutexCount=0; - if ( pVisibleDlgParent ) - nMutexCount = ImplSalReleaseYieldMutex(); + sal_uInt32 nMutexCount = 0; + WinSalInstance* pInst = GetSalData()->mpFirstInstance; + if ( pInst && pVisibleDlgParent ) + nMutexCount = pInst->ReleaseYieldMutex( true ); BYTE* pOutDevMode = (reinterpret_cast<BYTE*>(pOutBuffer) + pOutBuffer->mnDriverOffset); nRet = DocumentPropertiesW( hWnd, hPrn, pPrinterNameW, reinterpret_cast<LPDEVMODEW>(pOutDevMode), reinterpret_cast<LPDEVMODEW>(const_cast<BYTE *>(pInBuffer)), nMode ); - if ( pVisibleDlgParent ) - ImplSalAcquireYieldMutex( nMutexCount ); + if ( pInst && pVisibleDlgParent ) + pInst->AcquireYieldMutex( nMutexCount ); ClosePrinter( hPrn ); if( (nRet < 0) || (pVisibleDlgParent && (nRet == IDCANCEL)) ) @@ -1522,6 +1523,14 @@ bool WinSalPrinter::StartJob( const OUString* pFileName, return TRUE; } +void WinSalPrinter::DoEndDoc(HDC hDC) +{ + CATCH_DRIVER_EX_BEGIN; + if( ::EndDoc( hDC ) <= 0 ) + GetLastError(); + CATCH_DRIVER_EX_END( "exception in EndDoc", this ); +} + bool WinSalPrinter::EndJob() { HDC hDC = mhDC; @@ -1540,13 +1549,10 @@ bool WinSalPrinter::EndJob() // it should be safe to release the yield mutex over the EndDoc // call, however the real solution is supposed to be the threading // framework yet to come. - volatile sal_uLong nAcquire = GetSalData()->mpFirstInstance->ReleaseYieldMutex(); - CATCH_DRIVER_EX_BEGIN; - if( ::EndDoc( hDC ) <= 0 ) - GetLastError(); - CATCH_DRIVER_EX_END( "exception in EndDoc", this ); - - GetSalData()->mpFirstInstance->AcquireYieldMutex( nAcquire ); + { + SolarMutexReleaser aReleaser; + DoEndDoc( hDC ); + } DeleteDC( hDC ); mhDC = nullptr; } |