Windows NT 4.0 source code leak
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

//+-------------------------------------------------------------------
//
// 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__