Пример #1
0
BOOL FairMonitor::EndSynchronized()
{ 
  if( ! LockHeldByCallingThread() )
  {
    ::SetLastError(ERROR_INVALID_FUNCTION); // for the lack of better...
    return FALSE;
  }

  // Record the lock release for proper release in Wait().
  --m_nLockCount;

  // Release lock. Win32 allows no error checking here.
  ::LeaveCriticalSection(&m_critsecSynchronized); 
  
  return TRUE;
}
Пример #2
0
DWORD FairMonitor::Wait(
  DWORD dwMillisecondsTimeout/* = INFINITE*/,
  BOOL bAlertable/* = FALSE */
  )
{
  if( ! LockHeldByCallingThread() )
  {
    ::SetLastError(ERROR_INVALID_FUNCTION); // for the lack of better...
    return WAIT_FAILED;
  }

  // Enter a new event handle into the wait set.
  HANDLE hWaitEvent = Push();
  if( NULL == hWaitEvent )
    return WAIT_FAILED;

  // Store the current lock count for re-acquisition.
  int nThisThreadsLockCount = m_nLockCount;
  m_nLockCount = 0;

  // Release the synchronization lock the appropriate number of times.
  // Win32 allows no error checking here.
  for( int i=0; i<nThisThreadsLockCount; ++i)
    ::LeaveCriticalSection(&m_critsecSynchronized);

  // NOTE: Conceptually, releasing the lock and entering the wait
  // state is done in one atomic step. Technically, that is not
  // true here, because we first leave the critical section and
  // then, in a separate line of code, call WaitForSingleObjectEx.
  // The reason why this code is correct is that our thread is placed
  // in the wait set *before* the lock is released. Therefore, if
  // we get preempted right here and another thread notifies us, then
  // that notification will *not* be missed: the wait operation below
  // will find the event signalled.
  
  // Wait for the event to become signalled.
  DWORD dwWaitResult = ::WaitForSingleObjectEx(
    hWaitEvent,
    dwMillisecondsTimeout,
    bAlertable
    );

  // If the wait failed, store the last error because it will get
  // overwritten when acquiring the lock.
  DWORD dwLastError;
  if( WAIT_FAILED == dwWaitResult )
    dwLastError = ::GetLastError();

  // Acquire the synchronization lock the appropriate number of times.
  // Win32 allows no error checking here.
  for( int j=0; j<nThisThreadsLockCount; ++j)
    ::EnterCriticalSection(&m_critsecSynchronized);

  // Handle the wait timeout case.
  ::EnterCriticalSection(&m_critsecWaitSetProtection);
  std::deque<HANDLE>::const_iterator it_end = m_deqWaitSet.end();
  for ( std::deque<HANDLE>::const_iterator it = m_deqWaitSet.begin(); it < it_end; it++ )
  {
     if ((*it) == hWaitEvent)
     {
        m_deqWaitSet.erase(it);
        break;
     }
  }
  ::LeaveCriticalSection(&m_critsecWaitSetProtection);

  // Restore lock count.
  m_nLockCount = nThisThreadsLockCount;

  // Close event handle
  if( ! CloseHandle(hWaitEvent) )
    return WAIT_FAILED;

  if( WAIT_FAILED == dwWaitResult )
    ::SetLastError(dwLastError);

  return dwWaitResult;
}
Пример #3
0
DWORD Condition::Wait()
{
	DWORD dwMillisecondsTimeout = INFINITE;
	BOOL bAlertable = FALSE;
	ASSERT(LockHeldByCallingThread());

	// Enter a new event handle into the wait set.
	HANDLE hWaitEvent = Push();
	if( NULL == hWaitEvent )
		return WAIT_FAILED;

	// Store the current lock count for re-acquisition.
	int nThisThreadsLockCount = m_nLockCount;
	m_nLockCount = 0;

	// Release the synchronization lock the appropriate number of times.
	// Win32 allows no error checking here.
	for( int i=0; i<nThisThreadsLockCount; ++i)
	{
		//::LeaveCriticalSection(&m_critsecSynchronized);
		m_externalMutex->Release();
	}

	// NOTE: Conceptually, releasing the lock and entering the wait
	// state is done in one atomic step. Technically, that is not
	// true here, because we first leave the critical section and
	// then, in a separate line of code, call WaitForSingleObjectEx.
	// The reason why this code is correct is that our thread is placed
	// in the wait set *before* the lock is released. Therefore, if
	// we get preempted right here and another thread notifies us, then
	// that notification will *not* be missed: the wait operation below
	// will find the event signalled.

	// Wait for the event to become signalled.
	DWORD dwWaitResult = ::WaitForSingleObjectEx(
		hWaitEvent,
		dwMillisecondsTimeout,
		bAlertable
		);

	// If the wait failed, store the last error because it will get
	// overwritten when acquiring the lock.
	DWORD dwLastError = 0;
	if( WAIT_FAILED == dwWaitResult )
		dwLastError = ::GetLastError();

	// Acquire the synchronization lock the appropriate number of times.
	// Win32 allows no error checking here.
	for( int j=0; j<nThisThreadsLockCount; ++j)
	{
		//::EnterCriticalSection(&m_critsecSynchronized);
		m_externalMutex->Acquire();
	}

	// Restore lock count.
	m_nLockCount = nThisThreadsLockCount;

	// Close event handle
	if( ! CloseHandle(hWaitEvent) )
		return WAIT_FAILED;

	if( WAIT_FAILED == dwWaitResult )
		::SetLastError(dwLastError);

	return dwWaitResult;

}