📄 synobj.cpp
字号:
//***********************************************************************/
// Author : Garry
// Original Date : Sep 21, 2005
// Module Name : SYNOBJ.CPP
// Module Funciton :
// This module countains synchronization object's implementation
// code.
// The following synchronization object(s) is(are) defined
// in this file:
// 1. EVENT
// 2. MUTEX
// 3. SEMAPHORE
// 4. TIMER
//
// ************
// This file is the most important file of Hello China.
// ************
// Last modified Author :
// Last modified Date :
// Last modified Content :
// 1.
// 2.
// Lines number :
//***********************************************************************/
#ifndef __STDAFX_H__
#include "..\INCLUDE\StdAfx.h"
#endif
//Timer handler's parameter.
typedef struct{
__COMMON_OBJECT* lpSynObject; //Synchronous object.
__PRIORITY_QUEUE* lpWaitingQueue; //Waiting queue of the synchronous object.
__KERNEL_THREAD_OBJECT* lpKernelThread; //Kernel thread who want to wait.
}__TIMER_HANDLER_PARAM;
//Timer handler routine for all synchronous object.
static DWORD WaitingTimerHandler(LPVOID lpData)
{
__TIMER_HANDLER_PARAM* lpHandlerParam = (__TIMER_HANDLER_PARAM*)lpData;
DWORD dwFlags;
if(NULL == lpHandlerParam)
{
BUG();
return 0L;
}
__ENTER_CRITICAL_SECTION(NULL,dwFlags); //Acquire kernel thread object's spinlock.
switch(lpHandlerParam->lpKernelThread->dwWaitingStatus & OBJECT_WAIT_MASK)
{
case OBJECT_WAIT_RESOURCE:
case OBJECT_WAIT_DELETED:
break;
case OBJECT_WAIT_WAITING:
lpHandlerParam->lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
lpHandlerParam->lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_TIMEOUT;
//Delete the lpKernelThread from waiting queue.
lpHandlerParam->lpWaitingQueue->DeleteFromQueue(
(__COMMON_OBJECT*)lpHandlerParam->lpWaitingQueue,
(__COMMON_OBJECT*)lpHandlerParam->lpKernelThread);
//Add this kernel thread to ready queue.
lpHandlerParam->lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
KernelThreadManager.AddReadyKernelThread((__COMMON_OBJECT*)&KernelThreadManager,
lpHandlerParam->lpKernelThread);
break;
default:
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
BUG();
return 0L;
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return 0L;
}
//
//TimeOutWaiting is a global routine used by any synchronous objects' WaitForThisObjectEx
//routine.
//
DWORD TimeOutWaiting(__COMMON_OBJECT* lpSynObject, //Synchronous object.
__PRIORITY_QUEUE* lpWaitingQueue, //Waiting queue.
__KERNEL_THREAD_OBJECT* lpKernelThread, //Who want to wait.
DWORD dwMillionSecond) //Time out value in millionsecond.
{
__TIMER_OBJECT* lpTimerObj;
__TIMER_HANDLER_PARAM HandlerParam;
if((NULL == lpSynObject) || (NULL == lpWaitingQueue) ||
(NULL == lpKernelThread) || (0 == dwMillionSecond)) //Invalid parameters.
{
BUG();
return OBJECT_WAIT_FAILED;
}
//Initialize HandlerParam.
HandlerParam.lpKernelThread = lpKernelThread;
HandlerParam.lpSynObject = lpSynObject;
HandlerParam.lpWaitingQueue = lpWaitingQueue;
lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_WAITING;
//Set a one time timer.
lpTimerObj = (__TIMER_OBJECT*)System.SetTimer((__COMMON_OBJECT*)&System,
lpKernelThread,
#define TIMEOUT_WAITING_TIMER_ID 2048
TIMEOUT_WAITING_TIMER_ID,
dwMillionSecond,
WaitingTimerHandler,
(LPVOID)&HandlerParam,
TIMER_FLAGS_ONCE);
if(NULL == lpTimerObj)
{
return OBJECT_WAIT_FAILED;
}
KernelThreadManager.ScheduleFromProc(NULL); //Re-schedule.
//Once reach here,it means the waiting kernel thread was waken up.
switch(lpKernelThread->dwWaitingStatus & OBJECT_WAIT_MASK)
{
case OBJECT_WAIT_RESOURCE: //Got resource.
System.CancelTimer((__COMMON_OBJECT*)&System,
(__COMMON_OBJECT*)lpTimerObj); //Cancel timer.
return OBJECT_WAIT_RESOURCE;
case OBJECT_WAIT_DELETED: //Synchronous object was deleted.
System.CancelTimer((__COMMON_OBJECT*)&System,
(__COMMON_OBJECT*)lpTimerObj);
return OBJECT_WAIT_DELETED;
case OBJECT_WAIT_TIMEOUT: //Time out.
return OBJECT_WAIT_TIMEOUT;
default:
break;
}
//Once reach here,it means error encountered.
BUG();
return OBJECT_WAIT_FAILED;
}
//
//Routines pre-declaration.
//
static DWORD WaitForEventObject(__COMMON_OBJECT*);
static DWORD SetEvent(__COMMON_OBJECT*);
static DWORD ResetEvent(__COMMON_OBJECT*);
static DWORD WaitForEventObjectEx(__COMMON_OBJECT*,DWORD);
//---------------------------------------------------------------------------------
//
// SYNCHRONIZATION OBJECTS
//
//----------------------------------------------------------------------------------
//
//Event object's initializing routine.
//This routine initializes the members of an event object.
//
BOOL EventInitialize(__COMMON_OBJECT* lpThis)
{
BOOL bResult = FALSE;
__EVENT* lpEvent = NULL;
__PRIORITY_QUEUE* lpPriorityQueue = NULL;
if(NULL == lpThis)
goto __TERMINAL;
lpEvent = (__EVENT*)lpThis;
lpPriorityQueue = (__PRIORITY_QUEUE*)
ObjectManager.CreateObject(&ObjectManager,NULL,
OBJECT_TYPE_PRIORITY_QUEUE);
if(NULL == lpPriorityQueue)
goto __TERMINAL;
bResult = lpPriorityQueue->Initialize((__COMMON_OBJECT*)lpPriorityQueue);
if(!bResult)
goto __TERMINAL;
lpEvent->lpWaitingQueue = lpPriorityQueue;
lpEvent->dwEventStatus = EVENT_STATUS_OCCUPIED;
lpEvent->SetEvent = SetEvent;
lpEvent->ResetEvent = ResetEvent;
lpEvent->WaitForThisObjectEx = WaitForEventObjectEx;
lpEvent->WaitForThisObject = WaitForEventObject;
bResult = TRUE;
__TERMINAL:
if(!bResult)
{
if(NULL != lpPriorityQueue) //Release the priority queue.
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpPriorityQueue);
}
return bResult;
}
//
//Event object's uninitializing routine.
//Safety deleted is support by EVENT object,so in this routine,
//if there are kernel threads waiting for this object,then wakeup
//all kernel threads,and then destroy the event object.
//
VOID EventUninitialize(__COMMON_OBJECT* lpThis)
{
__EVENT* lpEvent = NULL;
__PRIORITY_QUEUE* lpPriorityQueue = NULL;
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
DWORD dwFlags;
if(NULL == lpThis)
{
BUG();
return;
}
lpEvent = (__EVENT*)lpThis;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
lpPriorityQueue = lpEvent->lpWaitingQueue;
if(EVENT_STATUS_FREE != EVENT_STATUS_FREE)
{
//Should wake up all kernel thread(s) who waiting for this object.
lpKernelThread = (__KERNEL_THREAD_OBJECT*)
lpPriorityQueue->GetHeaderElement(
(__COMMON_OBJECT*)lpPriorityQueue,
NULL);
while(lpKernelThread)
{
lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_DELETED;
KernelThreadManager.AddReadyKernelThread((__COMMON_OBJECT*)&KernelThreadManager,
lpKernelThread);
lpKernelThread = (__KERNEL_THREAD_OBJECT*)
lpPriorityQueue->GetHeaderElement(
(__COMMON_OBJECT*)lpPriorityQueue,
NULL);
}
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
ObjectManager.DestroyObject(&ObjectManager,
(__COMMON_OBJECT*)lpPriorityQueue); //*******CAUTION!!!************
//lpPriorityQueue->Uninitialize((__COMMON_OBJECT*)lpPriorityQueue);
return;
}
//
//The implementation of SetEvent.
//This routine do the following:
// 1. Saves the previous status into a local variable;
// 2. Sets the current status of the event to EVENT_STATUS_FREE;
// 3. Wakes up all kernel thread(s) in it's waiting queue.
// 4. Returns the previous status.
//
static DWORD SetEvent(__COMMON_OBJECT* lpThis)
{
DWORD dwPreviousStatus = EVENT_STATUS_OCCUPIED;
__EVENT* lpEvent = NULL;
__KERNEL_THREAD_OBJECT* lpKernelThread = NULL;
DWORD dwFlags = 0L;
if(NULL == lpThis)
return dwPreviousStatus;
lpEvent = (__EVENT*)lpThis;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
dwPreviousStatus = lpEvent->dwEventStatus;
lpEvent->dwEventStatus = EVENT_STATUS_FREE; //Set the current status to free.
//Wake up all kernel thread(s) waiting for this event.
lpKernelThread = (__KERNEL_THREAD_OBJECT*)
lpEvent->lpWaitingQueue->GetHeaderElement(
(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
NULL);
while(lpKernelThread) //Remove all kernel thread(s) from
//waiting queue.
{
lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
//Set waiting result bit.
lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_RESOURCE;
KernelThreadManager.AddReadyKernelThread(
(__COMMON_OBJECT*)&KernelThreadManager,
lpKernelThread); //Add to ready queue.
lpKernelThread = (__KERNEL_THREAD_OBJECT*)
lpEvent->lpWaitingQueue->GetHeaderElement(
(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
NULL);
}
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
if(IN_KERNELTHREAD()) //Current context is in process.
{
KernelThreadManager.ScheduleFromProc(NULL); //Re-schedule.
}
return dwPreviousStatus;
}
//
//The implementation of ResetEvent.
//
static DWORD ResetEvent(__COMMON_OBJECT* lpThis)
{
__EVENT* lpEvent = NULL;
DWORD dwPreviousStatus = 0L;
DWORD dwFlags = 0L;
if(NULL == lpThis)
return dwPreviousStatus;
lpEvent = (__EVENT*)lpThis;
__ENTER_CRITICAL_SECTION(NULL,dwFlags);
dwPreviousStatus = lpEvent->dwEventStatus;
lpEvent->dwEventStatus = EVENT_STATUS_OCCUPIED;
__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
return dwPreviousStatus;
}
//
//The implementation of WaitForEventObject.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -