Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
126 lines
3.6 KiB
C++
126 lines
3.6 KiB
C++
//==========================================================================;
|
|
//
|
|
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
// PURPOSE.
|
|
//
|
|
// Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
//--------------------------------------------------------------------------;
|
|
|
|
// support for a worker thread class to which you can asynchronously post
|
|
// messages
|
|
|
|
|
|
// Message class - really just a structure.
|
|
//
|
|
class CMsg {
|
|
public:
|
|
UINT uMsg;
|
|
DWORD dwFlags;
|
|
LPVOID lpParam;
|
|
CAMEvent *pEvent;
|
|
|
|
CMsg(UINT u, DWORD dw, LPVOID lp, CAMEvent *pEvnt)
|
|
: uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {}
|
|
|
|
CMsg()
|
|
: uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {}
|
|
};
|
|
|
|
// This is the actual thread class. It exports all the usual thread control
|
|
// functions. The created thread is different from a normal WIN32 thread in
|
|
// that it is prompted to perform particaular tasks by responding to messages
|
|
// posted to its message queue.
|
|
//
|
|
class AM_NOVTABLE CMsgThread {
|
|
private:
|
|
static DWORD WINAPI DefaultThreadProc(LPVOID lpParam);
|
|
DWORD m_ThreadId;
|
|
HANDLE m_hThread;
|
|
|
|
protected:
|
|
|
|
// if you want to override GetThreadMsg to block on other things
|
|
// as well as this queue, you need access to this
|
|
CGenericList<CMsg> m_ThreadQueue;
|
|
CCritSec m_Lock;
|
|
HANDLE m_hSem;
|
|
LONG m_lWaiting;
|
|
|
|
public:
|
|
CMsgThread()
|
|
: m_ThreadId(0),
|
|
m_hThread(NULL),
|
|
m_lWaiting(0),
|
|
m_hSem(NULL),
|
|
// make a list with a cache of 5 items
|
|
m_ThreadQueue(NAME("MsgThread list"), 5)
|
|
{
|
|
}
|
|
|
|
~CMsgThread();
|
|
// override this if you want to block on other things as well
|
|
// as the message loop
|
|
void virtual GetThreadMsg(CMsg *msg);
|
|
|
|
// override this if you want to do something on thread startup
|
|
virtual void OnThreadInit() {
|
|
};
|
|
|
|
BOOL CreateThread();
|
|
|
|
BOOL WaitForThreadExit(LPDWORD lpdwExitCode) {
|
|
if (m_hThread != NULL) {
|
|
WaitForSingleObject(m_hThread, INFINITE);
|
|
return GetExitCodeThread(m_hThread, lpdwExitCode);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD ResumeThread() {
|
|
return ::ResumeThread(m_hThread);
|
|
}
|
|
|
|
DWORD SuspendThread() {
|
|
return ::SuspendThread(m_hThread);
|
|
}
|
|
|
|
int GetThreadPriority() {
|
|
return ::GetThreadPriority(m_hThread);
|
|
}
|
|
|
|
BOOL SetThreadPriority(int nPriority) {
|
|
return ::SetThreadPriority(m_hThread, nPriority);
|
|
}
|
|
|
|
HANDLE GetThreadHandle() {
|
|
return m_hThread;
|
|
}
|
|
|
|
DWORD GetThreadId() {
|
|
return m_ThreadId;
|
|
}
|
|
|
|
|
|
void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags,
|
|
LPVOID lpMsgParam, CAMEvent *pEvent = NULL) {
|
|
CAutoLock lck(&m_Lock);
|
|
CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent);
|
|
m_ThreadQueue.AddTail(pMsg);
|
|
if (m_lWaiting != 0) {
|
|
ReleaseSemaphore(m_hSem, m_lWaiting, 0);
|
|
m_lWaiting = 0;
|
|
}
|
|
}
|
|
|
|
// This is the function prototype of the function that the client
|
|
// supplies. It is always called on the created thread, never on
|
|
// the creator thread.
|
|
//
|
|
virtual LRESULT ThreadMessageProc(
|
|
UINT uMsg, DWORD dwFlags, LPVOID lpParam, CAMEvent *pEvent) = 0;
|
|
};
|
|
|