//+-------------------------------------------------------------------------- // // Copyright (c) 1997-1999 Microsoft Corporation // // File: // // Contents: // // History: // //--------------------------------------------------------------------------- #ifndef __HANDLE_POOL_H__ #define __HANDLE_POOL_H__ #include #include #include "locks.h" ///////////////////////////////////////////////////////////////////////////// // // handle pool template class // // Note that STL's LIST class is used instead of VECTOR // ///////////////////////////////////////////////////////////////////////////// template class CHandlePool { private: long m_NumWaiting; // HUEIWANG 1/23/98 // C++ compiler 10.00.5256 can't compile STL // _STD list m_Handles; // STL's list typedef struct _HandleList { BOOL bAvailable; T m_Value; struct _HandleList *next; } HandleList, *LPHandleList; // // List of handles in the pool // LPHandleList m_Handles; DWORD m_TotalHandles; // // Semaphore for available handles // CTSemaphore<0, LONG_MAX> m_Available; // critical section guarding m_Handles. CCriticalSection m_CS; //DWORD m_MaxHandles; public: CHandlePool(); ~CHandlePool(); HRESULT AcquireHandle( T* pHandle, DWORD dwWaitFile=INFINITE ); BOOL AcquireHandleEx( IN HANDLE hWaitHandle, IN OUT T* pHandle, IN DWORD dwWaitFime=INFINITE ); void ReleaseHandle( T pRetHandle ); DWORD GetNumberAvailable(); DWORD GetMaxHandles() { return max; } }; //-------------------------------------------------------------------------------- template inline CHandlePool::CHandlePool() { // m_MaxHandles=max; m_NumWaiting=0; m_Handles=NULL; m_TotalHandles=0; } //-------------------------------------------------------------------------------- template inline CHandlePool::~CHandlePool() { // delete all handles still in cache // might result in handle leak. //for(_STD list::iterator it=m_Handles.begin(); it != m_Handles.end(); it++) // delete it; while(m_Handles) { LPHandleList ptr; ptr=m_Handles; m_Handles = m_Handles->next; delete ptr; } } //-------------------------------------------------------------------------------- template inline BOOL CHandlePool::AcquireHandleEx( IN HANDLE hWaitHandle, IN OUT T* pHandle, IN DWORD dwWaitFime /* infinite */ ) /* */ { BOOL bSuccess; InterlockedIncrement(&m_NumWaiting); bSuccess = m_Available.AcquireEx( hWaitHandle, dwWaitFime, FALSE ); // Available is a semaphore not mutex object. if(bSuccess == TRUE) { // Object Constructor will lock critical section and // destructor will unlock critical section CCriticalSectionLocker locker(m_CS); //assert(m_Handles.size()); //*pHandle = m_Handles.front(); //m_Handles.pop_front(); LPHandleList ptr; assert(m_Handles != NULL); *pHandle = m_Handles->m_Value; ptr=m_Handles; m_Handles = m_Handles->next; delete ptr; m_TotalHandles--; } InterlockedDecrement(&m_NumWaiting); return bSuccess; } //-------------------------------------------------------------------------------- template inline HRESULT CHandlePool::AcquireHandle( IN OUT T* pHandle, IN DWORD dwWaitFime /* infinite */ ) /* */ { DWORD status; InterlockedIncrement(&m_NumWaiting); status = m_Available.Acquire(dwWaitFime, FALSE); // Available is a semaphore not mutex object. if(status == WAIT_OBJECT_0) { // Object Constructor will lock critical section and // destructor will unlock critical section CCriticalSectionLocker locker(m_CS); //assert(m_Handles.size()); //*pHandle = m_Handles.front(); //m_Handles.pop_front(); LPHandleList ptr; assert(m_Handles != NULL); *pHandle = m_Handles->m_Value; ptr=m_Handles; m_Handles = m_Handles->next; delete ptr; m_TotalHandles--; status = ERROR_SUCCESS; } InterlockedDecrement(&m_NumWaiting); return status; } //-------------------------------------------------------------------------------- template inline void CHandlePool::ReleaseHandle( T pRetHandle ) /* */ { if(pRetHandle) { CCriticalSectionLocker lock(m_CS); if( InterlockedExchange(&m_NumWaiting, m_NumWaiting) > 0 || m_TotalHandles < max) { //m_Handles.push_back(pRetHandle); LPHandleList ptr; ptr = new HandleList; ptr->m_Value = pRetHandle; ptr->next = m_Handles; m_Handles = ptr; m_TotalHandles++; m_Available.Release(1); } else { // only cache so many handles. delete pRetHandle; } } return; } //-------------------------------------------------------------------------------- template inline DWORD CHandlePool::GetNumberAvailable() { UINT numAvailable; m_CS.Lock(); // numAvailable = m_Handles.size(); numAvailable = m_TotalHandles; m_CS.UnLock(); return numAvailable; } #endif