?? util.h
字號:
CUnboundedQueue<Type>::~CUnboundedQueue()
{
// In case someone is still waiting on
// this queue, try to avoid conflicts...
if (m_eventItems.Ready())
m_eventItems.Reset(); // no items to dequeue
if (m_rgpItems)
{
if (m_pfnItemDtor)
{
for (UINT i = 0; i < m_nUsed; i++)
{
m_pfnItemDtor(m_rgpItems[i]);
m_rgpItems[i] = NULL;
}
}
delete[] m_rgpItems;
}
m_nUsed = 0;
DeleteCriticalSection(&m_cs);
}
template <class Type>
BOOL CUnboundedQueue<Type>::Init(DWORD dwInitialSize)
{
if (m_rgpItems || dwInitialSize < 1)
return FALSE;
if (!m_eventItems.Init(TRUE, FALSE, TEXT("CUnboundedQueue_")))
return FALSE;
m_rgpItems = new Type*[dwInitialSize];
if (!m_rgpItems)
return FALSE;
m_dwInitialSize = dwInitialSize;
m_dwCurrentSize = dwInitialSize;
return TRUE;
}
template <class Type>
BOOL CUnboundedQueue<Type>::GrowQueue()
{
ASSERT(Ready());
DWORD dwNewSize = m_dwCurrentSize + m_dwInitialSize;
if ( dwNewSize < m_nUsed )
{
return FALSE;
}
Type ** rgpNewBuffer = new Type*[dwNewSize];
if (!rgpNewBuffer)
return FALSE;
memcpy(rgpNewBuffer, m_rgpItems, sizeof(Type*) * m_nUsed);
delete[] m_rgpItems;
m_rgpItems = rgpNewBuffer;
m_dwCurrentSize = dwNewSize;
return TRUE;
}
template <class Type>
BOOL CUnboundedQueue<Type>::Put(Type * const pItem)
{
ASSERT(Ready());
SYNCBLOCK(m_cs);
ASSERT(m_nUsed <= m_dwCurrentSize);
if (m_nUsed >= m_dwCurrentSize)
{
if (!GrowQueue())
return FALSE;
}
ASSERT(m_nUsed < m_dwCurrentSize);
// Put the element in our queue.
m_rgpItems[m_nUsed++] = pItem;
// There's something new in the queue,
// so signal waiting threads.
m_eventItems.Set();
return TRUE;
}
template <class Type>
BOOL CUnboundedQueue<Type>::Get(Type ** ppItem)
{
return ConditionalGet(NULL, 0, ppItem);
}
template <class Type>
BOOL CUnboundedQueue<Type>::Peek(Type ** ppItem)
{
ASSERT(Ready());
ASSERT(ppItem);
if (!ppItem)
return FALSE;
SYNCBLOCK(m_cs);
if (m_nUsed > 0)
{
// Copy the element from the queue.
*ppItem = m_rgpItems[0];
return TRUE;
}
else
{
return FALSE;
}
}
template <class Type>
HRESULT CUnboundedQueue<Type>::ConditionalGet(const PFN_QUEUE_TEST pfnTest,
const DWORD dwData,
Type** ppItem)
{
ASSERT(Ready());
ASSERT(ppItem);
if (!ppItem)
return S_FALSE;
SYNCBLOCK(m_cs);
if (m_nUsed > 0)
{
// Copy the element from the queue.
Type * pItem = m_rgpItems[0];
// If there is a condition, make sure
// it is satisfied.
if (pfnTest && !pfnTest(pItem, dwData))
return E_FAIL;
// One less in queue now...
m_nUsed--;
if (m_nUsed)
{
// Slide remaining items over to the beginning of the buffer.
memmove(m_rgpItems, (BYTE*)m_rgpItems + sizeof(Type*), sizeof(Type*) * m_nUsed);
}
else
{
// The last item was copied from the queue,
// so reset this event.
m_eventItems.Reset();
}
// NULL out the space that was freed up.
m_rgpItems[m_nUsed] = NULL;
// Set the output parameter.
*ppItem = pItem;
return S_OK;
}
else
{
return S_FALSE;
}
}
// Generic queue
template <class Type, UINT Size>
class CQueue
{
public:
CQueue(const BOOL fDontCallDestructors = FALSE);
virtual ~CQueue();
BOOL Init(const HANDLE hEvent);
BOOL Put(Type* const pItem, const DWORD dwTimeout);
HRESULT Get(Type*& rpItem, const DWORD dwTimeout);
BOOL Peek(Type*& rpItem);
HRESULT ConditionalGet(const PFN_QUEUE_TEST pfnTest, const DWORD dwData, Type*& rpItem,
const DWORD dwTimeout);
HRESULT WaitForNextItem(const DWORD dwTimeout);
HANDLE GetPutEvent() { return m_hPutEvent; }
void Enum(const PFN_QUEUE_ENUM pfnEnum, const DWORD dwData, const BOOL fClear);
BOOL FEmpty();
protected:
HRESULT GetInternal(Type*& rpItem, const DWORD dwTimeout);
BOOL PeekInternal(Type*& rpItem);
BOOL WaitForEmptySpaceInternal(const DWORD dwTimeout);
HRESULT WaitForNextItemInternal(const DWORD dwTimeout);
Type* m_rgpItems[Size];
UINT m_nUsed;
HANDLE m_hGetEvent;
HANDLE m_hPutEvent;
HANDLE m_hCancelEvent;
CRITICAL_SECTION m_cs;
BOOL m_fDontCallDestructors;
BOOL m_fInited;
};
// Priority queue
template <class Type, UINT Size>
class CPriorityQueue : public CQueue<Type, Size>
{
public:
CPriorityQueue();
~CPriorityQueue();
BOOL Put(Type* const pItem, const DWORD dwTimeout);
};
// Function to be passed to CDblList::Enum().
// This function should return TRUE for enumeration to stop.
typedef BOOL (*PFN_LIST_ENUM)(void* pItem, DWORD dwData);
// Generic doubly-linked list
template <class Type>
class CDblList
{
public:
CDblList();
~CDblList();
BOOL Add(Type* const pAdd);
BOOL Remove(const Type* const pRemove);
void Enum(const PFN_LIST_ENUM pfnEnum, const DWORD dwData);
private:
Type* m_pElems;
CRITICAL_SECTION m_cs;
};
//
// Template definitions
//
//
// Queue ctor
//
template <class Type, UINT Size>
CQueue<Type, Size>::CQueue(const BOOL fDontCallDestructors /* = FALSE */)
: m_nUsed(0),
m_hGetEvent(NULL),
m_hPutEvent(NULL),
m_hCancelEvent(NULL),
m_fDontCallDestructors(fDontCallDestructors),
m_fInited(FALSE)
{
// Initialize the critical section
InitializeCriticalSection(&m_cs);
for (UINT i = 0; i < Size; i++) {
m_rgpItems[i] = NULL;
}
}
//
// Queue dtor
//
template <class Type, UINT Size>
CQueue<Type, Size>::~CQueue()
{
// Get rid of the events
if (m_hPutEvent) {
(void)CloseHandle(m_hPutEvent);
}
if (m_hGetEvent) {
(void)CloseHandle(m_hGetEvent);
}
// Delete the elements still in the queue
for (UINT i = 0; i < m_nUsed; i++) {
if (m_fDontCallDestructors) {
// NOTE: We use this to avoid useless asserts when this destructor (called from RIL driver) frees
// memory allocated by RIL proxy
LocalFree(m_rgpItems[i]);
} else {
delete m_rgpItems[i];
}
}
// Get rid of the critical section
DeleteCriticalSection(&m_cs);
}
//
// Initalize the queue
//
template <class Type, UINT Size>
BOOL CQueue<Type, Size>::Init(const HANDLE hEvent)
{
DEBUGCHK(hEvent != NULL);
// If the queue is already initialized, skip this
if (m_fInited) {
goto Success;
}
// Create the events
m_hGetEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!m_hGetEvent) {
goto Error;
}
m_hPutEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!m_hPutEvent) {
goto Error;
}
m_hCancelEvent = hEvent;
m_fInited = TRUE;
Success:
return TRUE;
Error:
if (m_hGetEvent) {
(void)CloseHandle(m_hGetEvent);
}
return FALSE;
}
//
// Enqueue an element
//
template <class Type, UINT Size>
BOOL CQueue<Type, Size>::Put(Type* const pNew, const DWORD dwTimeout)
{
SYNCBLOCK(m_cs);
DEBUGCHK(FALSE != m_fInited);
DEBUGCHK(pNew != NULL);
BOOL fRet = FALSE;
if (m_fInited) {
if (!WaitForEmptySpaceInternal(dwTimeout)) {
goto Error;
}
// We have space in the queue
if ( m_nUsed >= Size )
{
ASSERT( FALSE );
goto Error;
}
m_rgpItems[m_nUsed] = pNew;
m_nUsed++;
// Signal the Put event
(void)SetEvent(m_hPutEvent);
}
fRet = TRUE;
Error:
return fRet;
}
//
// Dequeue an element
//
template <class Type, UINT Size>
HRESULT CQueue<Type, Size>::Get(Type*& rpItem, const DWORD dwTimeout)
{
SYNCBLOCK(m_cs);
return GetInternal(rpItem, dwTimeout);
}
//
// Dequeue an element (internal version)
//
template <class Type, UINT Size>
HRESULT CQueue<Type, Size>::GetInternal(Type*& rpItem, const DWORD dwTimeout)
{
DEBUGCHK(FALSE != m_fInited);
HRESULT hr = S_OK;
// Initialize the returned pointer in case we fail
rpItem = NULL;
if (m_fInited) {
hr = WaitForNextItemInternal(dwTimeout);
if (FAILED(hr)) {
goto Error;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -