windows-nt/Source/XPSP1/NT/sdktools/mtscript/inc/thrdcomm.h
2020-09-26 16:20:57 +08:00

151 lines
5 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: thrdcomm.h
//
// Contents: Contains the inter-thread communication class
//
//----------------------------------------------------------------------------
//****************************************************************************
//
// Forward declarations
//
//****************************************************************************
class CThreadComm;
//****************************************************************************
//
// Classes
//
//****************************************************************************
//+---------------------------------------------------------------------------
//
// Class: CThreadComm (ctc)
//
// Purpose: Base class which handles cross-thread communication. This
// is the only class with methods that can safely be called
// by any thread. All other classes must have their methods
// called by their owning thread (except the ctor/dtor and Init
// which are called by the creating thread).
//
//----------------------------------------------------------------------------
class CThreadComm : public IUnknown, public CThreadLock
{
public:
DECLARE_MEMCLEAR_NEW_DELETE();
// Thread-unsafe member functions - can only be called by owning (or
// creating) thread.
CThreadComm();
~CThreadComm();
HRESULT StartThread(void * pvParams);
BOOL Shutdown(CThreadComm * pTarget);
static DWORD TempThreadRoutine(LPVOID pvParam);
virtual DWORD ThreadMain() = 0;
// Used to tell StartThread that the new thread is going and has picked
// up all of its parameters.
// If fSuccess is false, then the thread will be terminating
// immediatly, and StartThread() will wait for it to do so.
void ThreadStarted(HRESULT hrThread) {
_hrThread = hrThread;
SetEvent(_hThreadReady); // Signal the other thread
::Sleep(100); // Yield to the other thread
}
BOOL GetNextMsg(THREADMSG *tm, void * pData, DWORD *cbData);
void Reply(DWORD dwReply);
void SetName(LPCSTR szName);
// -----------------------------------------------------------------
//
// Thread-safe member functions - can be called by any thread.
HANDLE hThread() { return _hThread; }
void PostToThread(CThreadComm *pTarget, THREADMSG tm, void * pData = NULL, DWORD cbData = 0);
DWORD SendToThread(CThreadComm *pTarget, THREADMSG tm, void * pData = NULL, DWORD cbData = 0);
// End of thread-safe member list
//
// -----------------------------------------------------------------
protected:
virtual BOOL Init();
//
// Every method on objects that derive from CThreadComm should have
// VERIFY_THREAD at the beginning. VERIFY_THREAD ensures that the proper
// thread is calling the method (i.e. it ensure that proper apartment rules
// are being followed.)
//
inline void VERIFY_THREAD() { Assert(GetCurrentThreadId() == _dwThreadId); }
HANDLE _hThreadReady; // Event signaled when the new thread has set its return value
HANDLE _hCommEvent; // Event signaled when there is a message
DWORD _dwThreadId;
HANDLE _hThread;
void * _pvParams;
HRESULT _hrThread; // The new thread sets this for initial success/failure.
private:
//
// MSGDATABUFSIZE: Max size of a thread message. The -40 is to keep the
// MESSAGEDATA struct below 1K.
//
#define MSGDATABUFSIZE (1024 - 40)
//
// MESSAGEDATA: All the data associated with a thread message.
//
struct MESSAGEDATA
{
MESSAGEDATA *pNext;
THREADMSG tmMessage;
DWORD dwResult;
HANDLE hResultEvt;
DWORD cbData;
BYTE bData[MSGDATABUFSIZE];
};
#if DBG == 1
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // == 0x1000
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} THREADNAME_INFO;
#endif
DWORD SendHelper(THREADMSG tm,
void * pData,
DWORD cbData,
BOOL fSend,
HANDLE hResultEvt);
// ***************************
// THREAD-SAFE MEMBER DATA
// All access to the following members must be protected by LOCK_LOCALS()
//
MESSAGEDATA *_pMsgData; // Linked list of messages
BOOL _fInSend; // True if we're inside SendToThread -
// needed to catch deadlock situations.
MESSAGEDATA * _pMsgReply; // Place where we need to put our reply
HANDLE _hResultEvt; // Event used to indicate that the result
// is ready.
};