151 lines
5 KiB
C++
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.
|
|
};
|
|
|
|
|