mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.2 KiB
190 lines
5.2 KiB
//+-------------------------------------------------------------------
|
|
//
|
|
// File: threads.hxx
|
|
//
|
|
// Contents: Rpc thread cache
|
|
//
|
|
// Classes: CRpcThread - single thread
|
|
// CRpcThreadCache - cache of threads
|
|
//
|
|
// Notes: This code represents the cache of Rpc threads used to
|
|
// make outgoing calls in the APARTMENT object Rpc
|
|
// model.
|
|
//
|
|
// History: Rickhi Created
|
|
// 07-31-95 Rickhi Fix event handle leak
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
#ifndef __THREADS_HXX__
|
|
#define __THREADS_HXX__
|
|
|
|
#include <olesem.hxx>
|
|
|
|
|
|
// inactive thread timeout. this is how long a thread will sit idle
|
|
// in the thread cache before deleting itself.
|
|
|
|
#define THREAD_INACTIVE_TIMEOUT 30000 // in milliseconds
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Class: CRpcThread
|
|
//
|
|
// Purpose: Represents one thread in the cache of Rpc callout
|
|
// threads.
|
|
//
|
|
// Notes: In order to make Rpc calls in the OLE Single-Threaded
|
|
// model, we must leave the main thread and perform the
|
|
// blocking Rpc call on a worker thread. This object
|
|
// represents such a worker thread.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
class CRpcThread
|
|
{
|
|
public:
|
|
CRpcThread(void *param);
|
|
~CRpcThread();
|
|
|
|
// dispatch methods
|
|
void Dispatch(void *param);
|
|
void WorkerLoop();
|
|
CRpcThread * GetNext(void) { return _pNext; }
|
|
void SetNext(CRpcThread *pNext) { _pNext = pNext; }
|
|
|
|
// cleanup methods
|
|
void WakeAndExit();
|
|
|
|
private:
|
|
|
|
HANDLE _hWakeup; // thread wakeup event
|
|
BOOL _fDone; // completion flag
|
|
|
|
void * _param; // parameter packet
|
|
CRpcThread * _pNext; // next thread in free list
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Class: CRpcThreadCache
|
|
//
|
|
// Purpose: Holds a cache of Rpc threads. It finds the first
|
|
// free CRpcThread or creates a new one and dispatches
|
|
// the call to it.
|
|
//
|
|
// Notes: the free list is kept in a most recently used order
|
|
// so that uneeded threads can time out and go away.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
class CRpcThreadCache
|
|
{
|
|
public:
|
|
CRpcThreadCache(void) { _pFreeList = NULL; }
|
|
// no dtor since nothing to do
|
|
|
|
// dispatch methods
|
|
HRESULT Dispatch(void *param);
|
|
void AddToFreeList(CRpcThread *pThrd);
|
|
|
|
// cleanup methods
|
|
void RemoveFromFreeList(CRpcThread *pThrd);
|
|
void ClearFreeList(void);
|
|
|
|
private:
|
|
|
|
static DWORD _stdcall RpcWorkerThreadEntry(void *param);
|
|
|
|
CRpcThread * _pFreeList; // list of free threads
|
|
COleStaticMutexSem _mxs; // for list manipulation
|
|
};
|
|
|
|
|
|
// Rpc SendReceive thread pool. This must be static to handle Rpc threads
|
|
// that block and dont return until after CoUninitialize has been called.
|
|
|
|
extern CRpcThreadCache RpcThreadCache;
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CRpcThread::Dispatch
|
|
//
|
|
// Purpose: wakes up a thread blocked in WorkerLoop.
|
|
//
|
|
// Notes: folks who want to execute code on another thread
|
|
// call this method. It fills in the parameter packet
|
|
// and wakes up the sleeping thread.
|
|
//
|
|
// Callers: Called ONLY by the COM thread.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
inline void CRpcThread::Dispatch(void *param)
|
|
{
|
|
CairoleDebugOut((DEB_CHANNEL,
|
|
"Dispatch pThrd:%x param:%x\n", this, param));
|
|
|
|
// set the call info and the completion event
|
|
_param = param;
|
|
|
|
// signal the Rpc thread to wakeup
|
|
SetEvent(_hWakeup);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CRpcThread::WakeAndExit
|
|
//
|
|
// Purpose: Tells the thread object to free itself
|
|
//
|
|
// Note: This is called by CRpcThreadCache::RemoveFromFreeList
|
|
// when we want to free this thread, eg at ProcessUninitialize.
|
|
//
|
|
// Callers: Called by the COM thread OR worker thread.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
inline void CRpcThread::WakeAndExit()
|
|
{
|
|
// _fDone should only be set inside this function and in the
|
|
// constructor. _fDone must only ever transition from FALSE
|
|
// to TRUE and that must only happen once in the life of this
|
|
// object.
|
|
|
|
Win4Assert(_fDone == FALSE);
|
|
_fDone = TRUE;
|
|
|
|
CairoleDebugOut((DEB_CHANNEL,
|
|
"CRpcThreadCache:WakeAndExit pThrd:%x _hWakeup:%x\n", this, _hWakeup));
|
|
|
|
SetEvent(_hWakeup);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Member: CRpcThreadCache::AddToFreeLlist
|
|
//
|
|
// Purpose: puts a thread back onto the free list after the
|
|
// thread has completed its job.
|
|
//
|
|
// Callers: Called ONLY by worker thread.
|
|
//
|
|
//+-------------------------------------------------------------------
|
|
inline void CRpcThreadCache::AddToFreeList(CRpcThread *pThrd)
|
|
{
|
|
COleStaticLock lck(_mxs);
|
|
|
|
// place this thread on the front of the free list. it is
|
|
// important that we add and remove only from the front of
|
|
// the list so that unused threads will eventually time out
|
|
// and release themselves...that is, it keeps our thread pool
|
|
// as small as possible.
|
|
|
|
pThrd->SetNext(_pFreeList);
|
|
_pFreeList = pThrd;
|
|
}
|
|
|
|
|
|
#endif // __THREADS_HXX__
|