⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.h

📁 ril source code for Windows CE
💻 H
📖 第 1 页 / 共 3 页
字号:
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 + -