📄 thread.cpp
字号:
#include "GOS.h"
#include "thread.h"
#define MSG_WAIT 0x01L
#define PTR_MASK ~0x3L
#define REMOVEMSG(prev,pTmp,next) \
if(pPrev)pPrev->pNext=next;else m_pMQEntry=next;\
pTmp->pNext=m_pMQFree;m_pMQFree=pTmp
CThread::CThread()
{
m_pMQEntry=NULL;
m_pMQFree=NULL;
m_pMQBuffer=NULL;
m_pWaitObject=NULL;
m_pStack=NULL;
m_nPriority=0;
}
BOOL CThread::CreateThread(PVOID pParam,int nPriority,UINT nStackSize,int nFlags)
{
PVOID pBlock;
m_nWakeTime=GetTickCount();
if(nFlags & CreateSuspend)
m_nWakeTime+=MAXLONG;
pBlock=g_pKernel->MemoryAlloc(NULL,
nStackSize?nStackSize:ThreadDefaultStackSize);
m_pStack=PVOID(DWORD(pBlock)+_msize(pBlock)-sizeof(DWORD));
m_heap.Create(pBlock);
g_pHAL->CreateThread(this,pParam);
g_pKernel->ThreadTableAdd(this,nPriority);
return TRUE;
}
BOOL CThread::ExitThread(DWORD dwExitCode)
{
MsgProc(msgExitThread,dwExitCode,0);
SetLastError(dwExitCode);
RemoveAllMessage();
g_pKernel->MemoryAlloc(m_heap.Delete(),0);
g_pKernel->ThreadTableRemove(this);
g_pHAL->ExitThread(this);
return TRUE;
}
VOID CThread::SleepEx(LONG nMilliseconds,BOOL bSleepTo)
{
if(bSleepTo)
m_nWakeTime=nMilliseconds;
else
m_nWakeTime=GetTickCount()+nMilliseconds;
SwitchToThread();
}
int CThread::OnRun(PVOID pData)
{
MSG msg;
while(GetMessage(&msg,INFINITE) &&
!(msg.message==msgQuit && msg.pObj==this))
{
DispatchMessage(&msg);
}
ExitThread(msg.wParam);
return msg.wParam;
}
LRESULT CThread::MsgProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case msgGetMQThread:
wParam=LRESULT(this);
break;
case msgRunThread:
wParam=OnRun(PVOID(wParam));
break;
default:
wParam=CMsgObject::MsgProc(message,wParam,lParam);
}
return wParam;
}
BOOL CThread::GetMessage(PMSG pMsg,LONG nTimeOut)
{
PMSGLE pCur,pPrev=NULL;
LONG nWake,nCurTime=GetTickCount();
nTimeOut+=nCurTime;
m_tlock.Lock(INFINITE);
pCur=m_pMQEntry;
for(;;)
{
if(!pCur)
{
if(LONG(nTimeOut-nCurTime)<=0)
break;
m_nWakeTime=nTimeOut;
*PDWORD(&m_pMQBuffer) |= MSG_WAIT;
m_tlock.Unlock();
SwitchToThread();
*PDWORD(&m_pMQBuffer) &= ~MSG_WAIT;
m_tlock.Lock(INFINITE);
pCur=m_pMQEntry;
nCurTime=GetTickCount();
continue;
}
else if(IsEventMessage(pCur->msg.message))
{
if(pCur->msg.pObj)
{
*pMsg=pCur->msg;
pMsg->message=msgEvent;
pCur->msg.pObj=NULL;
break;
}
}
else if(IsTimerMessage(pCur->msg.message))
{
nWake=pCur->msg.wParam;
if(LONG(nCurTime-nWake)>=0)
{
pMsg->pObj=pCur->msg.pObj;
pMsg->message=msgTimer;
pMsg->wParam=LOWORD(pCur->msg.lParam);
pMsg->lParam=nWake;
pCur->msg.wParam=nWake=HIWORD(pCur->msg.lParam) +
((pMsg->wParam & 0x8000)?nWake:nCurTime);
break;
}
if(LONG(nTimeOut-nWake)>0)
nTimeOut=nWake;
}
else
{
*pMsg=pCur->msg;
REMOVEMSG(pPrev,pCur,pCur->pNext);
break;
}
pPrev=pCur;
pCur=pCur->pNext;
}
m_tlock.Unlock();
return BOOL(pCur);
}
LRESULT CThread::DispatchMessage(const MSG *pMsg)
{
LRESULT lResult;
CMsgObject* pObj=pMsg->pObj;
if(pObj)
{
lResult=pObj->MsgProc(pMsg->message,pMsg->wParam,pMsg->lParam);
}
else if(pMsg->message==msgSendMessage)
{
CMutex* lock=(CMutex*)pMsg->wParam;
PMSG m=PMSG(pMsg->lParam);
m->wParam=m->pObj->MsgProc(m->message,m->wParam,m->lParam);
lock->Unlock();
lResult=TRUE;
}
else lResult=0;
return lResult;
}
HANDLE CThread::InsertMessage(CMsgObject* pObj,UINT nMessage,WPARAM wParam,LPARAM lParam)
{
PMSGLE pIns=NULL,pTmp,pPrev=NULL,pNext;
m_tlock.Lock(INFINITE);
for(pTmp=m_pMQEntry;pTmp;pPrev=pTmp,pTmp=pNext)
{
pNext=pTmp->pNext;
if(pTmp->msg.message>=nMessage)
{
if(pTmp->msg.message>nMessage)
break;
if(pTmp->msg.pObj==pObj && IsUniqueMessage(nMessage))
{
pIns=pTmp;
break;
}
}
}
if(!pIns)
{
if(!m_pMQFree)
GrowMQBuffer();
pIns=m_pMQFree;
m_pMQFree=pIns->pNext;
if(pPrev)
{
pIns->pNext=pTmp;
pPrev->pNext=pIns;
}
else
{
pIns->pNext=m_pMQEntry;
m_pMQEntry=pIns;
}
pIns->msg.pObj=pObj;
pIns->msg.message=nMessage;
}
pIns->msg.wParam=wParam;
pIns->msg.lParam=lParam;
m_tlock.Unlock();
if(DWORD(m_pMQBuffer) & MSG_WAIT)
SleepEx(0,FALSE);
return HANDLE(pIns);
}
HANDLE CThread::InsertMessage(CMsgObject* pObj,HANDLE hRefMsg,WPARAM wParam,LPARAM lParam)
{
PMSGLE pIns,pRefMsg=PMSGLE(hRefMsg);
m_tlock.Lock(INFINITE);
if(!m_pMQFree)
GrowMQBuffer();
pIns=m_pMQFree;
m_pMQFree=pIns->pNext;
pIns->pNext=pRefMsg->pNext;
pRefMsg->pNext=pIns;
pIns->msg.message=pRefMsg->msg.message;
pIns->msg.pObj=pObj;
pIns->msg.wParam=wParam;
pIns->msg.lParam=lParam;
m_tlock.Unlock();
if(DWORD(m_pMQBuffer) & MSG_WAIT)
SleepEx(0,FALSE);
return HANDLE(pIns);
}
void CThread::PulseMessage(HANDLE hMsg)
{
if(DWORD(m_pMQBuffer) & MSG_WAIT)
SleepEx(0,FALSE);
}
BOOL CThread::RemoveMessage(CMsgObject* pObj)
{
PMSGLE pTmp,pPrev=NULL,pNext;
DWORD nCount=0;
m_tlock.Lock(INFINITE);
for(pTmp=m_pMQEntry;pTmp;pTmp=pNext)
{
pNext=pTmp->pNext;
if(pTmp->msg.pObj==pObj)
{
nCount++;
REMOVEMSG(pPrev,pTmp,pNext);
}
pPrev=pTmp;
}
m_tlock.Unlock();
return nCount;
}
BOOL CThread::RemoveMessage(CMsgObject* pObj,UINT nMessage)
{
PMSGLE pTmp,pPrev=NULL,pNext;
DWORD nCount=0;
m_tlock.Lock(INFINITE);
for(pTmp=m_pMQEntry;pTmp;pTmp=pNext)
{
pNext=pTmp->pNext;
if(pTmp->msg.message>=nMessage)
{
if(pTmp->msg.message>nMessage)
break;
if(pTmp->msg.pObj==pObj)
{
nCount++;
REMOVEMSG(pPrev,pTmp,pNext);
if(IsUniqueMessage(nMessage))
break;
}
}
pPrev=pTmp;
}
m_tlock.Unlock();
return nCount;
}
BOOL CThread::RemoveMessage(HANDLE hMsgFrom,HANDLE hMsgTo)
{
PMSGLE pFrom=PMSGLE(hMsgFrom),pTo=PMSGLE(hMsgTo);
PMSGLE pTmp,pPrev=NULL;
m_tlock.Lock(INFINITE);
for(pTmp=m_pMQEntry;pTmp;pPrev=pTmp,pTmp=pTmp->pNext)
{
if(pTmp==pFrom)
{
if(pPrev)
pPrev->pNext=pTo->pNext;
else
m_pMQEntry=pTo->pNext;
pTo->pNext=m_pMQFree;
m_pMQFree=pFrom;
break;
}
}
m_tlock.Unlock();
return BOOL(pTmp);
}
BOOL CThread::RemoveTimerMessage(CMsgObject* pObj,UINT nIDEvent)
{
PMSGLE pTmp,pPrev=NULL,pNext;
m_tlock.Lock(INFINITE);
for(pTmp=m_pMQEntry;pTmp;pPrev=pTmp,pTmp=pNext)
{
pNext=pTmp->pNext;
if(IsTimerMessage(pTmp->msg.message))
{
if(pTmp->msg.pObj==pObj && LOWORD(pTmp->msg.lParam)==nIDEvent)
{
REMOVEMSG(pPrev,pTmp,pNext);
break;
}
}
}
m_tlock.Unlock();
return BOOL(pTmp);
}
BOOL CThread::GrowMQBuffer()
{
PMSGLE pTmp,pBuf,pBufEnd;
DWORD nSize=MsgQueueGrowSize*sizeof(MSGLE);
pBuf=(PMSGLE)g_pKernel->MemoryAlloc(NULL,nSize+sizeof(PMSGLE));
m_pMQFree=pBuf;
pBufEnd=PMSGLE(DWORD(pBuf)+nSize);
nSize=DWORD(m_pMQBuffer);
pBufEnd->pNext=PMSGLE(nSize & PTR_MASK);
nSize &= MSG_WAIT;
nSize |= DWORD(pBuf);
m_pMQBuffer=PMSGLE(nSize);
for(pTmp=pBuf+1;pTmp<pBufEnd;pBuf=pTmp,pTmp++)
pBuf->pNext=pTmp;
pBuf->pNext=NULL;
return TRUE;
}
void CThread::RemoveAllMessage()
{
DWORD nSize=MsgQueueGrowSize*sizeof(MSGLE);
PMSGLE pBufEnd,pBuf;
m_tlock.Lock(INFINITE);
pBuf=PMSGLE(DWORD(m_pMQBuffer) & PTR_MASK);
m_pMQBuffer=NULL;
m_pMQEntry=NULL;
m_pMQFree=NULL;
m_tlock.Unlock();
while(pBuf)
{
pBufEnd=PMSGLE(DWORD(pBuf)+nSize);
g_pKernel->MemoryAlloc(pBuf,0);
pBuf=pBufEnd->pNext;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -