Kaydet (Commit) ea2be4ef authored tarafından Michael Stahl's avatar Michael Stahl

vcl: document the non-obvious WinSalInstance's WaitMutex members

Change-Id: I004f082c9e4a17aeb7a8bd778bf45dff93e47ee8
üst 482c52e9
......@@ -27,11 +27,21 @@ class SalYieldMutex;
class WinSalInstance : public SalInstance
{
public:
HINSTANCE mhInst; // Instance Handle
HWND mhComWnd; // window, for communication (between threads and the main thread)
SalYieldMutex* mpSalYieldMutex; // Sal-Yield-Mutex
osl::Mutex* mpSalWaitMutex; // Sal-Wait-Mutex
sal_uInt16 mnYieldWaitCount; // Wait-Count
/// Instance Handle
HINSTANCE mhInst;
/// invisible Window so non-main threads can SendMessage() the main thread
HWND mhComWnd;
/// The Yield mutex ensures that only one thread calls into VCL
SalYieldMutex* mpSalYieldMutex;
/// The Wait mutex ensures increment of mnYieldWaitCount and acquisition
/// or release of mpSalYieldMutex is atomic
osl::Mutex* mpSalWaitMutex;
/// count main thread's pending ImplSalYieldMutexAcquireWithWait() calls
/// (it's not clear to me if this will be > 1 in practice; it would be
/// possible if main thread's handling of SAL_MSG_* sent by other threads
/// via SendMessage() ends up calling ImplSalYieldMutexAcquireWithWait())
sal_uInt16 mnYieldWaitCount;
public:
WinSalInstance();
virtual ~WinSalInstance();
......
......@@ -159,6 +159,8 @@ void SalYieldMutex::release()
// Java clients doesn't come in the right order
GdiFlush();
// lock here to ensure that the test of mnYieldWaitCount and
// m_mutex.release() is atomic
mpInstData->mpSalWaitMutex->acquire();
if ( mpInstData->mnYieldWaitCount )
PostMessageW( mpInstData->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
......@@ -203,16 +205,19 @@ sal_uLong SalYieldMutex::GetAcquireCount( sal_uLong nThreadId )
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()
{
WinSalInstance* pInst = GetSalData()->mpFirstInstance;
if ( !pInst )
return;
// If we are the main thread, then we must wait with wait, because
// in if we don't reschedule, then we create deadlocks if a Windows
// Function is called from another thread. If we aren't the main thread,
// than we call acquire directly.
// If this is the main thread, then we must wait with GetMessage(),
// because if we don't reschedule, then we create deadlocks if a Window's
// create/destroy is called via SendMessage() from another thread.
// If this is not the main thread, call acquire directly.
DWORD nThreadId = GetCurrentThreadId();
SalData* pSalData = GetSalData();
if ( pSalData->mnAppThreadId == nThreadId )
......@@ -233,13 +238,26 @@ void ImplSalYieldMutexAcquireWithWait()
}
else
{
// other threads must not observe mnYieldWaitCount == 0
// while main thread is blocked in GetMessage()
pInst->mnYieldWaitCount++;
pInst->mpSalWaitMutex->release();
MSG aTmpMsg;
// this call exists because it dispatches SendMessage() msg!
GetMessageW( &aTmpMsg, pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, SAL_MSG_RELEASEWAITYIELD );
// it is possible that another thread acquires and releases
// mpSalYieldMutex after the GetMessage call returns,
// observes mnYieldWaitCount != 0 and sends an extra
// SAL_MSG_RELEASEWAITYIELD - but that appears unproblematic
// as it will just cause the next Yield to do an extra
// iteration of the while loop here
pInst->mnYieldWaitCount--;
if ( pInst->mnYieldWaitCount )
{
// repeat the message so that the next instance of this
// function further up the call stack is unblocked too
PostMessageW( pInst->mhComWnd, SAL_MSG_RELEASEWAITYIELD, 0, 0 );
}
}
}
}
......@@ -701,6 +719,8 @@ LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPar
case SAL_MSG_RELEASEWAITYIELD:
{
WinSalInstance* pInst = GetSalData()->mpFirstInstance;
// this test does not need mpSalWaitMutex locked because
// it can only happen on the main thread
if ( pInst && pInst->mnYieldWaitCount )
PostMessageW( hWnd, SAL_MSG_RELEASEWAITYIELD, wParam, lParam );
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment