// CriticalSection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include "CriticalSection.h"
// thread priority map table
static const int ThreadPriorityMap[THREAD_PRIOR_LEVELS] =
{
THREAD_PRIORITY_TIME_CRITICAL,
THREAD_PRIORITY_HIGHEST,
THREAD_PRIORITY_ABOVE_NORMAL,
THREAD_PRIORITY_NORMAL,
THREAD_PRIORITY_BELOW_NORMAL,
THREAD_PRIORITY_LOWEST,
THREAD_PRIORITY_IDLE
};
/*********************************************************************
implementation of manipulating functions of LBCriticalSection object
*********************************************************************/
VOID WINAPI EnterLBCriticalSection(LPLB_CRITICAL_SECTION pcsLBCriticalSection)
{
DWORD dwState;
HANDLE hCurrentThread;
hCurrentThread = (HANDLE)GetCurrentThreadId();
// if current thread recurse call EnterLBCriticalSection(),
// then just return, this action avoid deadlock
if(hCurrentThread == pcsLBCriticalSection->OwningThread
&& pcsLBCriticalSection->LockCount >= 0)
{
pcsLBCriticalSection->RecurionCount++;
return;
}
// test semaphore to see if critical section is available
dwState = WaitForSingleObject(pcsLBCriticalSection->LockSemaphore, 0);
switch(dwState)
{
// can enter into critical section
case WAIT_OBJECT_0:
pcsLBCriticalSection->LockCount++;
pcsLBCriticalSection->RecurionCount++;
pcsLBCriticalSection->OwningThread = hCurrentThread;
return;
// cannot enter into critical section, waiting until critical section
// is available and the thread to run is current thread.
case WAIT_TIMEOUT:
while(1)
{
dwState = WaitForSingleObject(pcsLBCriticalSection->LockSemaphore, INFINITE);
// if current thread is the one to be resumed, then return;
// otherwise, release control first, and then keep waiting.
if(WAIT_OBJECT_0 == dwState && pcsLBCriticalSection->OwningThread == hCurrentThread)
{
pcsLBCriticalSection->LockCount++;
pcsLBCriticalSection->RecurionCount++;
return;
}
else if(WAIT_OBJECT_0 == dwState && pcsLBCriticalSection->OwningThread != hCurrentThread)
{
// give up gained control, because current thread is not the one to run.
ReleaseSemaphore(pcsLBCriticalSection->LockSemaphore, 1, NULL);
}
else
{
// other occasions are error.
// error handling
}
}
break;
// error
case WAIT_FAILED:
default:
// error handling
break;
}
}
VOID WINAPI LeaveLBCriticalSection(LPLB_CRITICAL_SECTION pcsLBCriticalSection)
{
HANDLE hCurrentThread;
HANDLE hNextThread;
hCurrentThread = (HANDLE)GetCurrentThreadId();
// validating, this condition should always be true,
// that only the thread in critical section can call Leave function,
// otherwise there must be an error occured
if(hCurrentThread == pcsLBCriticalSection->OwningThread)
{
// deal with recursion
if(pcsLBCriticalSection->RecurionCount > 0)
{
pcsLBCriticalSection->RecurionCount--;
return;
}
else
{
// select a thread to run, according thread priority rank
hNextThread = OutWaitThreadQueue(pcsLBCriticalSection->WaitThreadQueueHead);
// if need to hand over the ownership of critical section
// to another thread, then set OwningThread to the target
// thread, else do nothing.
if(hNextThread)
{
pcsLBCriticalSection->OwningThread = hNextThread;
}
// it's time to release ownership
pcsLBCriticalSection->LockCount--;
ReleaseSemaphore(pcsLBCriticalSection->LockSemaphore, 1, NULL);
}
}
else
{
// other thread cannot leave before enter the critical section
// error handling
}
}
VOID WINAPI InitializeLBCriticalSection(LPLB_CRITICAL_SECTION pcsLBCriticalSection)
{
int index;
pcsLBCriticalSection->LockCount = -1;
pcsLBCriticalSection->RecurionCount = 0;
pcsLBCriticalSection->OwningThread = 0;
for(index = 0; index < THREAD_PRIOR_LEVELS; index++)
{
pcsLBCriticalSection->WaitThreadQueueHead[index].nPriority = ThreadPriorityMap[index];
pcsLBCriticalSection->WaitThreadQueueHead[index].head = NULL;
pcsLBCriticalSection->WaitThreadQueueHead[index].tail = NULL;
}
pcsLBCriticalSection->LockSemaphore = CreateSemaphore(NULL, 1, MAX_THREADS_IN_PROCESS, NULL);
if(!pcsLBCriticalSection->LockSemaphore)
{
// error handling
}
}
BOOL WINAPI TryEnterLBCriticalSection(IN OUT LPLB_CRITICAL_SECTION lpcsLBCriticalSection)
{
DWORD dwState = WaitForSingleObject(lpcsLBCriticalSection->LockSemaphore, 0);
if(WAIT_OBJECT_0 == dwState)
{
return (TRUE);
}
return (FALSE);
}
VOID WINAPI DeleteLBCriticalSection(LPLB_CRITICAL_SECTION pcsLBCriticalSection)
{
int index;
HANDLE hThread;
CloseHandle(pcsLBCriticalSection->LockSemaphore);
//pcsLBCriticalSection->LockCount = -1;
//pcsLBCriticalSection->RecurionCount = 0;
for(index = 0; index < THREAD_PRIOR_LEVELS; index++)
{
// terminate all other threads, except current thread itself.
hThread = OutWaitThreadQueue(pcsLBCriticalSection->WaitThreadQueueHead);
while(hThread && hThread != pcsLBCriticalSection->OwningThread)
{
TerminateThread(hThread, 0);
hThread = OutWaitThreadQueue(pcsLBCriticalSection->WaitThreadQueueHead);
}
}
delete pcsLBCriticalSection;
}
/*************************************************************************
implement assistant queue manipulating functions
*************************************************************************/
static BOOL InWaitThreadQueue(
WAIT_THREAD_QUEUE_HEAD * QueueArray,
int nPriority,
HANDLE hThread
)
{
WAIT_THREAD_QUEUE_NODE * node;
WAIT_THREAD_QUEUE_HEAD * queue;
// map into proper queue
switch(nPriority)
{
case THREAD_PRIORITY_TIME_CRITICAL:
queue = QueueArray;
break;
case THREAD_PRIORITY_HIGHEST:
queue = QueueArray + 1;
break;
case THREAD_PRIORITY_ABOVE_NORMAL:
queue = QueueArray + 2;
break;
case THREAD_PRIORITY_NORMAL:
queue = QueueArray + 3;
break;
case THREAD_PRIORITY_BELOW_NORMAL:
queue = QueueArray + 4;
break;
case THREAD_PRIORITY_LOWEST:
queue = QueueArray + 5;
break;
case THREAD_PRIORITY_IDLE:
queue = QueueArray + 6;
break;
default:
return (FALSE);
}
// alloc new queue node and setting
node = (WAIT_THREAD_QUEUE_NODE *)malloc(sizeof(WAIT_THREAD_QUEUE_NODE));
if(!node)
{
return (FALSE);
}
node->hWaitingThread = hThread;
node->next = NULL;
// append to queue tail
if(!queue->head && !queue->tail)
{
queue->tail = queue->head = node;
return (TRUE);
}
else
{
queue->tail = queue->tail->next = node;
return (TRUE);
}
return (FALSE);
}
static HANDLE OutWaitThreadQueue(WAIT_THREAD_QUEUE_HEAD * QueueArray)
{
int index;
HANDLE hThread;
WAIT_THREAD_QUEUE_NODE * node;
WAIT_THREAD_QUEUE_HEAD * queue;
for(index = 0; index < THREAD_PRIOR_LEVELS; index++)
{
queue = QueueArray + index;
if(queue->head)
{
// get and check the queue's head node
node = queue->head;
if(!node)
{
return (NULL);
}
// adapting the queue, return needed value
queue->head = queue->head->next;
hThread = node->hWaitingThread;
free(node);
return (hThread);
}
}
return (NULL);
}
CriticalSection.rar_CriticalSection
版权申诉
123 浏览量
2022-09-23
23:37:38
上传
评论
收藏 4KB RAR 举报
林当时
- 粉丝: 95
- 资源: 1万+
最新资源
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- 【ERP标准流程-标准流程-进货管理】(DOC 17页).doc
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- Java爬虫项目【项目开发计划】(共12页).docx
- 11111111111
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
- MyBatis动态SQL是一种强大的特性,它允许我们在SQL语句中根据条件动态地添加或删除某些部分,从而实现更加灵活和高效的数据
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈