ioftpd read/write 锁实现

//z ioftpd read/write 锁实现
//z 2014-05-09 18:05:41 L.236'21259 BG57IV3@XCL T3344801563.K.F1390913624[T5,L93,R3,V252]
#define LOCK_MAX_COUNT	10000

typedef struct _LOCKOBJECT
{
	HANDLE			hEvent[2];
	LONG volatile	lExclusive;
} LOCKOBJECT, *LPLOCKOBJECT;

VOID ReleaseExclusiveLock(LPLOCKOBJECT lpLockObject);
VOID AcquireExclusiveLock(LPLOCKOBJECT lpLockObject);
VOID ReleaseSharedLock(LPLOCKOBJECT lpLockObject);
VOID AcquireSharedLock(LPLOCKOBJECT lpLockObject);
VOID DeleteLockObject(LPLOCKOBJECT lpLockObject);
BOOL InitializeLockObject(LPLOCKOBJECT lpLockObject);

//z 2014-05-09 16:53:25 L.236'25595 T1731279863.K[T3,L97,R3,V51]
//z 初始化。
BOOL InitializeLockObject(LPLOCKOBJECT lpLockObject)
{
	//z 默认不是排他的
	lpLockObject->lExclusive	= FALSE;
	//z Event,人工重置事件,初始化状态为已通知。
	lpLockObject->hEvent[0]	= CreateEvent(NULL, TRUE, TRUE, NULL);
	if (lpLockObject->hEvent[0] == INVALID_HANDLE_VALUE) return FALSE;
	
	//z 用于 share 锁,控制reader数量
	lpLockObject->hEvent[1]	= CreateSemaphore(NULL, LOCK_MAX_COUNT, LOCK_MAX_COUNT, 0);
	if (!lpLockObject->hEvent[1])
	{
		CloseHandle(lpLockObject->hEvent[0]);
		lpLockObject->hEvent[0] = INVALID_HANDLE_VALUE;
		return FALSE;
	}
	return TRUE;
}

//dtor
VOID DeleteLockObject(LPLOCKOBJECT lpLockObject)
{
	HANDLE hEvent;

	hEvent = lpLockObject->hEvent[0];
	//z 关闭 event;做一些必要的检测
	if (hEvent && (hEvent != INVALID_HANDLE_VALUE))
	{
		CloseHandle(hEvent);
	}
	//z 关闭后,将其设置为 INVALID_HANDLE_VALUE
	lpLockObject->hEvent[0] = INVALID_HANDLE_VALUE;

	hEvent = lpLockObject->hEvent[1];
	if (hEvent && (hEvent != INVALID_HANDLE_VALUE))
	{
		CloseHandle(hEvent);
	}
	lpLockObject->hEvent[1] = INVALID_HANDLE_VALUE;
}

//z 获取共享锁。
VOID AcquireSharedLock(LPLOCKOBJECT lpLockObject)
{
	//z 得同时在这两个 event 上等待
	//z 在人工重置事件上等待成功后,没有变更其状态,等待成功之后,还是已通知状态。
	//z 由semaphore来控制read的数量。
	WaitForMultipleObjects(2, lpLockObject->hEvent, TRUE, INFINITE);
}

//z 释放shared lock
VOID ReleaseSharedLock(LPLOCKOBJECT lpLockObject)
{
	ReleaseSemaphore(lpLockObject->hEvent[1], 1, NULL);
}

//z 获取排它锁
VOID AcquireExclusiveLock(LPLOCKOBJECT lpLockObject)
{
	LONG	lCount, lLeft;

	//z 获取排他性,如果此时 lExclusive 为true,那么其已经被其他排它锁持有,那么就在其上等待
	while (InterlockedExchange(&lpLockObject->lExclusive, TRUE)) WaitForSingleObject(lpLockObject->hEvent[0], INFINITE);
	//z 当前 lExclusive 为 false 或者其他排它锁释放了该锁(重置为已通知状态)。
	//z 获取排它锁成功;将event置为未通知状态。这样其他排它锁无法获取。
	ResetEvent(lpLockObject->hEvent[0]);
	
	//z 然后在读取锁上等待;既然是排他的,那么read锁也得排除,可能更改内容
	for (;;)
	{
		//z 这个等待主要是为了获取下一句 lCount
		//z 在count大于0时,为已通知状态。等待成功,则count减少1。
		WaitForSingleObject(lpLockObject->hEvent[1], INFINITE);
		//z count 增加1,lCount获取之前的 count 数目。加上这个释放的,现在一共有 (lCount+1)个
		ReleaseSemaphore(lpLockObject->hEvent[1], 1, &lCount);
		//z 还剩下多少需要等待
		lLeft	= (LOCK_MAX_COUNT - 1) - lCount;
		//z 没有需要等待的,获取排它锁成功
		if (! lLeft) break;
		
		//z 放弃时间片
		if (lLeft < 10)
		{
			//z SwitchToThread():只要有可调度线程,即便优先级较低,也会让其调度。
			SwitchToThread();
		}
		//z sleep ,放弃线程拥有的剩余时间片;与上述区别是 Sleep(0):时间片只能让给优先级相同或更高的线程;
		else Sleep(10);
	}
}

VOID ReleaseExclusiveLock(LPLOCKOBJECT lpLockObject)
{
	//z 注意与上述获取排它锁的过程的顺序对比下。
	//z 先重置事件为通知状态
	SetEvent(lpLockObject->hEvent[0]);
	//z 设置 lExclusive 为 FALSE,以供其他等待的排它锁可用。
	InterlockedExchange(&lpLockObject->lExclusive, FALSE);
}


posted @ 2014-05-09 18:03  BiG5  阅读(238)  评论(0编辑  收藏  举报