⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utsem.h

📁 vc6.0完整版
💻 H
📖 第 1 页 / 共 2 页
字号:

/* ----------------------------------------------------------------------------
@mfunc 

	SYNCHRO class - Constructor

	Create the event, initialize the critical section objects and reader count,
	and return.
---------------------------------------------------------------------------- */
inline UTSemCheapReadWrite::UTSemCheapReadWrite(void)
{
	// Create the manual-reset event (the only init that can fail)
	hevReadDone = CreateEvent(NULL, TRUE, TRUE, NULL);
	hevReaderPresent = CreateEvent(NULL, TRUE, FALSE, NULL);
	hevWriterPresent = CreateEvent(NULL, TRUE, FALSE, NULL);

	fInitSucceeded = (hevReadDone != NULL) && 
						(hevReaderPresent != NULL) && 
						(hevWriterPresent != NULL);

	// If we created the event, proceed with the risk-free initialization
	if (fInitSucceeded)
	{
		cReaders = -1;
		cWriters = -1;
		m_fReader = FALSE;
		InitializeCriticalSection(&csExclusive);
		InitializeCriticalSection(&csReader);
		InitializeCriticalSection(&csWriter);
	}

	return;
}


/* ----------------------------------------------------------------------------
@mfunc 

	SYNCHRO class - Destructor

	Free the event, delete the critical section objects, and return.
---------------------------------------------------------------------------- */
inline UTSemCheapReadWrite::~UTSemCheapReadWrite(void)
{
	if (IsValid())
	{
		CloseHandle(hevReadDone);
		DeleteCriticalSection(&csExclusive);
		DeleteCriticalSection(&csReader);
	}

	return;
}




/* ----------------------------------------------------------------------------
@mfunc 

	SYNCHRO class - Lock member function
---------------------------------------------------------------------------- */
inline BOOL UTSemCheapReadWrite::Lock(SYNCH_LOCK_TYPE lt)
{
	// Verify that the object is valid
	if (! IsValid())
		return FALSE;

	// Verify that the specified lock type is supported by this implementation
	if (lt == SLT_READPROMOTE)
		return FALSE;

	// Claim the read lock or write lock as specified
	if (lt == SLT_READ)
	{
		// First try to get the reader lock cheaply by incrementing
		// the reader count.  Only if reader count is positive
		// do we try and test that a reader is present
		if (InterlockedIncrement (&cReaders) > 0)
		{
			// Test that there is actually a reader holding on the the lock.
			// It is possible to that the reader count is greater that -1
			// but still there are no readers who have actually acquired the
			// lock
			if (WaitForSingleObject (hevReaderPresent, 0) == WAIT_OBJECT_0)
			{
				// Only if there are no writers waiting to acquire the lock
				// do we try to acquire the lock. Without this we cannot
				// guarantee that the writer wont starve.
				if (WaitForSingleObject (hevWriterPresent, 0) == WAIT_TIMEOUT)
					return TRUE;
			}
		}

		// Decrement extra reader count
		InterlockedDecrement (&cReaders);

		// Claim the <csExclusive> critical section.  This call blocks if there's
		// an active writer or if there's a writer waiting for active readers to
		// complete.
		EnterCriticalSection(&csExclusive);

		// Claim access to the reader count.  If this blocks, it's only for the
		// briefest moment, while other threads go through to increment or
		// decrement the reader count.
		EnterCriticalSection(&csReader);

		// Increment the reader count.  If this is the first reader, we reset the
		// hevReadDone event so that the next writer blocks.
		if (InterlockedIncrement (&cReaders) >= 0)
		{
			if (!m_fReader)
			{
				SetEvent (hevReaderPresent);
				ResetEvent(hevReadDone);
				m_fReader = TRUE;
			}
		}

		// Release access to the reader count
		LeaveCriticalSection(&csReader);

		// Release access to the <csExclusive> critical section.  This enables
		// other readers to come through and the next writer to wait for active
		// readers to complete (which in turn prevents new readers from entering).
		LeaveCriticalSection(&csExclusive);
	}
	else
	{
		// Verify that since this isn't the read lock, that it's the write lock
		Assert(lt == SLT_WRITE);

		// Gain access to the writer count
		EnterCriticalSection(&csWriter);

		// Increment the writer count.  If this is the writer reader, we set the
		// hevWriterPresent event so that new readers give way to the writer.
		if (InterlockedIncrement (&cWriters) == 0)
		{
			SetEvent (hevWriterPresent);
		}

		// Release access to the writer count
		LeaveCriticalSection(&csWriter);

		// Claim the <csExclusive> critical section.  This not only prevents other
		// threads from claiming the write lock, but also prevents any new threads
		// from claiming the read lock.
		EnterCriticalSection(&csExclusive);

		// Wait for the active readers to release their read locks.
		return WaitForSingleObject(hevReadDone, INFINITE) == WAIT_OBJECT_0;
	}

	return TRUE;
} //End Lock



/* ----------------------------------------------------------------------------
@mfunc 

	SYNCHRO class - Unlock member function
---------------------------------------------------------------------------- */
inline BOOL UTSemCheapReadWrite::UnLock(SYNCH_LOCK_TYPE lt)
{
	// Verify that the object is valid
	if (! IsValid())
		return FALSE;

	// Verify that the specified lock type is supported by this implementation
	if (lt == SLT_READPROMOTE)
		return FALSE;

	// Release the read lock or write lock as specified
	if (lt == SLT_READ)
	{
		// Claim access to the reader count.  If this blocks, it's only for the
		// briefest moment, while other threads go through to increment or
		// decrement the reader count.
		EnterCriticalSection(&csReader);

		// Decrement the reader count.  If this is the last reader, set 
		// <hevReadDone>, which allows the first waiting writer to proceed.
		if (InterlockedDecrement (&cReaders) < 0)
		{
			ResetEvent (hevReaderPresent);
			SetEvent(hevReadDone);
			m_fReader = FALSE;
		}

		// Release access to the reader count
		LeaveCriticalSection(&csReader);
	}
	else
	{
		// Verify that since this isn't the read lock, that it's the write lock
		Assert(lt == SLT_WRITE);
		
		// Gain access to the writer count
		EnterCriticalSection(&csWriter);

		// Decrement the writer count.  If this is the last writer, we reset the
		// hevWriterPresent event.
		if (InterlockedDecrement (&cWriters) < 0)
		{
			ResetEvent (hevWriterPresent);
		}

		// Release access to the writer count
		LeaveCriticalSection(&csWriter);

		// Make <csExclusive> available to one other writer or to the first reader
		LeaveCriticalSection(&csExclusive);
	}

	return TRUE;
} //End Unlock



/* ----------------------------------------------------------------------------
@class CSemExclusive:

	@rev 	0 	| 4th Feb,95 | GaganC 		| Created
---------------------------------------------------------------------------- */
class CSemExclusive
{
public:
	CSemExclusive (void);
	~CSemExclusive (void);
	void Lock (void);
	void UnLock (void);
private:
	CRITICAL_SECTION m_csx;
};	//end class CSemExclusive




//-----------------------------------------------------------------------------
//
//		IMPLEMENTATION of class CSemExclusive
//
//-----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
@mfunc 
---------------------------------------------------------------------------- */
inline CSemExclusive::CSemExclusive 
	(
		void
	)
{
	InitializeCriticalSection (&m_csx);
}

/* ----------------------------------------------------------------------------
@mfunc 

---------------------------------------------------------------------------- */
inline CSemExclusive::~CSemExclusive 
	(
		void
	)
{
	DeleteCriticalSection (&m_csx);
}


/* ----------------------------------------------------------------------------
@mfunc 
---------------------------------------------------------------------------- */
inline void CSemExclusive::Lock
	(
		void
	)
{
	EnterCriticalSection (&m_csx);
}


/* ----------------------------------------------------------------------------
@mfunc 
---------------------------------------------------------------------------- */
inline void CSemExclusive::UnLock
	(
		void
	)
{
	LeaveCriticalSection (&m_csx);
}






/* ----------------------------------------------------------------------------
@class CSemExclusiveSL:

---------------------------------------------------------------------------- */
class CSemExclusiveSL
{
public:
	CSemExclusiveSL (void);
	~CSemExclusiveSL (void);

	void Lock (void);
	void UnLock (void);
private:
	DWORD volatile m_dwLock;
	DWORD volatile *m_pdwLock;
	DWORD volatile m_dwOwningThread;
	ULONG volatile m_ulRecursionCount;
};


/* ----------------------------------------------------------------------------
@mfunc 

---------------------------------------------------------------------------- */
inline CSemExclusiveSL::CSemExclusiveSL ( void )
{
	m_dwOwningThread = 0;
	m_ulRecursionCount = 0;
	m_dwLock = 0;
	m_pdwLock = &m_dwLock;
}


/* ----------------------------------------------------------------------------
@mfunc 

---------------------------------------------------------------------------- */
inline CSemExclusiveSL::~CSemExclusiveSL ( void )
{
	//Nothing to do
}


/* ----------------------------------------------------------------------------
@mfunc 

**  Lock -- Obtains an SMP safe lock on the address given.
**	WARNING: Does not release any semaphore or critsec when waiting.
**

@rev 0  Created 04/20/93 by LaleD 
@rev 1	modified 7/13/96 by shaiwals
---------------------------------------------------------------------------- */
inline void CSemExclusiveSL::Lock ( void )
{
    DWORD	i;
	DWORD	n	=	0;
    int		m	=	0;


startover:

	if (InterlockedExchange((long *)m_pdwLock, 1) == 0)
	{
		m_dwOwningThread = GetCurrentThreadId();
		return;
	}

	if (m_dwOwningThread == GetCurrentThreadId())
	{
		m_ulRecursionCount++;
		return;
	}

	// Give away my time slice to another thread as the probability
	// of my getting this lock right away are low - shaiwals
	//Sleep (1); 

	/* retry using safe test only after cheaper, unsafe test succeeds */
	for (i = 0 ; i < (DWORD)(10000) ; i++)
	{
		if (*m_pdwLock == 0)
		{
			goto startover;
		}
	}

	/*
	**  Yield after hitting the cspinctr limit
	**    Sleep(0) only yields to threads of same priority
	**    if hit limit 10000 times, sleep 5sec and test for kill
	**    this provides a chance to CTRL-C it if stuck in loop
	*/
	
	m++;

	if( ( m % 10000 ) == 0)
	{
		Sleep(5000);
	}
	else
	{
		Sleep(0);
	}

	goto startover;
	/* try again */
}

/* ----------------------------------------------------------------------------
@mfunc 

---------------------------------------------------------------------------- */
inline void CSemExclusiveSL::UnLock ( void )
{
	AssertSz (m_dwOwningThread == GetCurrentThreadId(), \
						"Lock released by someone who doesnt own the lock!!!");

	if (m_ulRecursionCount > 0)
	{
		m_ulRecursionCount--;
		return;
	}

	m_dwOwningThread = 0;
	*m_pdwLock = 0;
}



#endif __UTSEM_H__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -