OSQueue用法

#ifndef _OSQUEUE_H_
#define _OSQUEUE_H_

#include "MyAssert.h"
#include "OSHeaders.h"
#include "OSMutex.h"
#include "OSCond.h"
#include "OSThread.h"

#define OSQUEUETESTING 0

class OSQueue;

class OSQueueElem {
    public:
        OSQueueElem(void* enclosingObject = NULL) : fNext(NULL), fPrev(NULL), fQueue(NULL),
                                                    fEnclosingObject(enclosingObject) {}
        virtual ~OSQueueElem() { Assert(fQueue == NULL); }

        Bool16 IsMember(const OSQueue& queue) { return (&queue == fQueue); }
        Bool16 IsMemberOfAnyQueue()     { return fQueue != NULL; }
        void* GetEnclosingObject()  { return fEnclosingObject; }
        void SetEnclosingObject(void* obj) { fEnclosingObject = obj; }

        OSQueueElem* Next() { return fNext; }
        OSQueueElem* Prev() { return fPrev; }
        OSQueue* InQueue()  { return fQueue; }
        inline void Remove();

    private:

        OSQueueElem*    fNext;
        OSQueueElem*    fPrev;
		//每个元素内部通过队列指针能够判断出该元素是否是该队列中的元素,同时也可以通过该元素直接从队列中将自己删除
        OSQueue *       fQueue;
        void*           fEnclosingObject;

        friend class    OSQueue;
};

class OSQueue {
    public:
        OSQueue();
        ~OSQueue() {}

		//进队
        void            EnQueue(OSQueueElem* object);
		//出队
        OSQueueElem*    DeQueue();

		//获取队头元素
        OSQueueElem*    GetHead() { if (fLength > 0) return fSentinel.fPrev; return NULL; }
		//获取队尾元素
        OSQueueElem*    GetTail() { if (fLength > 0) return fSentinel.fNext; return NULL; }
		//获取队列长度
        UInt32          GetLength() { return fLength; }
        //删除某个元素
        void            Remove(OSQueueElem* object);

#if OSQUEUETESTING
        static Bool16       Test();
#endif

    protected:
		//双向链表头节点,不存储任何元素,使插入删除元素方便
        OSQueueElem     fSentinel;
        UInt32          fLength;
};

class OSQueueIter
{
    public:
		//默认让fCurrentElemP指向队列头
        OSQueueIter(OSQueue* inQueue) : fQueueP(inQueue), fCurrentElemP(inQueue->GetHead()) {}
		//让fCurrentElemP指向startElemP,startElemP必须是队列中的元素,如果不是则让fCurrentElemP指向空
        OSQueueIter(OSQueue* inQueue, OSQueueElem* startElemP ) : fQueueP(inQueue)
            {
                if ( startElemP )
                {   Assert( startElemP->IsMember(*inQueue ) );
                    fCurrentElemP = startElemP;
                
                }
                else
                    fCurrentElemP = NULL;
            }
        ~OSQueueIter() {}
        //重置当前元素位置,使其为队列头
        void            Reset() { fCurrentElemP = fQueueP->GetHead(); }
        //获取当前元素
        OSQueueElem*    GetCurrent() { return fCurrentElemP; }
		//fCurrentElemP指向下一个元素
        void            Next();
        //队列空了
        Bool16          IsDone() { return fCurrentElemP == NULL; }
        
    private:
		//队列指针
        OSQueue*        fQueueP;
		//队列指向的当前元素
        OSQueueElem*    fCurrentElemP;
};

class OSQueue_Blocking
{
    public:
        OSQueue_Blocking() {}
        ~OSQueue_Blocking() {}
        //出队列,如果队列没有元素,则阻塞,直到调用EnQueue发出信号后,才解除阻塞
        OSQueueElem*    DeQueueBlocking(OSThread* inCurThread, SInt32 inTimeoutInMilSecs);
		//出队列,不会阻塞,如果队列没有元素,则直接返回空
        OSQueueElem*    DeQueue();//will not block
		//每次入队列的时候,都会调用Signal发出信号
        void            EnQueue(OSQueueElem* obj);
        
        OSCond*         GetCond()   { return &fCond; }
        OSQueue*        GetQueue()  { return &fQueue; }
        
    private:

        OSCond              fCond;
        OSMutex             fMutex;
        OSQueue             fQueue;
};


void    OSQueueElem::Remove()
{
    if (fQueue != NULL)
        fQueue->Remove(this);
}
#endif //_OSQUEUE_H_



#include "OSQueue.h"


OSQueue::OSQueue() : fLength(0)
{
    fSentinel.fNext = &fSentinel;
    fSentinel.fPrev = &fSentinel;
}

void OSQueue::EnQueue(OSQueueElem* elem)
{
    Assert(elem != NULL);
    if (elem->fQueue == this)
        return;
    Assert(elem->fQueue == NULL);
    elem->fNext = fSentinel.fNext;
    elem->fPrev = &fSentinel;
    elem->fQueue = this;
    fSentinel.fNext->fPrev = elem;
    fSentinel.fNext = elem;
    fLength++;
}

OSQueueElem* OSQueue::DeQueue()
{
    if (fLength > 0)
    {
        OSQueueElem* elem = fSentinel.fPrev;
        Assert(fSentinel.fPrev != &fSentinel);
        elem->fPrev->fNext = &fSentinel;
        fSentinel.fPrev = elem->fPrev;
        elem->fQueue = NULL;
        fLength--;
        return elem;
    }
    else
        return NULL;
}

void OSQueue::Remove(OSQueueElem* elem)
{
    Assert(elem != NULL);
    Assert(elem != &fSentinel);
    
    if (elem->fQueue == this)
    {
        elem->fNext->fPrev = elem->fPrev;
        elem->fPrev->fNext = elem->fNext;
        elem->fQueue = NULL;
        fLength--;
    }
}

#if OSQUEUETESTING
Bool16 OSQueue::Test()
{
    OSQueue theVictim;
    void *x = (void*)1;
    OSQueueElem theElem1(x);
    x = (void*)2;
    OSQueueElem theElem2(x);
    x = (void*)3;
    OSQueueElem theElem3(x);
    
    if (theVictim.GetHead() != NULL)
        return false;
    if (theVictim.GetTail() != NULL)
        return false;
    
    theVictim.EnQueue(&theElem1);
    if (theVictim.GetHead() != &theElem1)
        return false;
    if (theVictim.GetTail() != &theElem1)
        return false;
    
    OSQueueElem* theElem = theVictim.DeQueue();
    if (theElem != &theElem1)
        return false;
    
    if (theVictim.GetHead() != NULL)
        return false;
    if (theVictim.GetTail() != NULL)
        return false;
    
    theVictim.EnQueue(&theElem1);
    theVictim.EnQueue(&theElem2);

    if (theVictim.GetHead() != &theElem1)
        return false;
    if (theVictim.GetTail() != &theElem2)
        return false;
        
    theElem = theVictim.DeQueue();
    if (theElem != &theElem1)
        return false;

    if (theVictim.GetHead() != &theElem2)
        return false;
    if (theVictim.GetTail() != &theElem2)
        return false;

    theElem = theVictim.DeQueue();
    if (theElem != &theElem2)
        return false;

    theVictim.EnQueue(&theElem1);
    theVictim.EnQueue(&theElem2);
    theVictim.EnQueue(&theElem3);

    if (theVictim.GetHead() != &theElem1)
        return false;
    if (theVictim.GetTail() != &theElem3)
        return false;

    theElem = theVictim.DeQueue();
    if (theElem != &theElem1)
        return false;

    if (theVictim.GetHead() != &theElem2)
        return false;
    if (theVictim.GetTail() != &theElem3)
        return false;

    theElem = theVictim.DeQueue();
    if (theElem != &theElem2)
        return false;

    if (theVictim.GetHead() != &theElem3)
        return false;
    if (theVictim.GetTail() != &theElem3)
        return false;

    theElem = theVictim.DeQueue();
    if (theElem != &theElem3)
        return false;

    theVictim.EnQueue(&theElem1);
    theVictim.EnQueue(&theElem2);
    theVictim.EnQueue(&theElem3);
    
    OSQueueIter theIterVictim(&theVictim);
    if (theIterVictim.IsDone())
        return false;
    if (theIterVictim.GetCurrent() != &theElem3)
        return false;
    theIterVictim.Next();
    if (theIterVictim.IsDone())
        return false;
    if (theIterVictim.GetCurrent() != &theElem2)
        return false;
    theIterVictim.Next();
    if (theIterVictim.IsDone())
        return false;
    if (theIterVictim.GetCurrent() != &theElem1)
        return false;
    theIterVictim.Next();
    if (!theIterVictim.IsDone())
        return false;
    if (theIterVictim.GetCurrent() != NULL)
        return false;

    theVictim.Remove(&theElem1);

    if (theVictim.GetHead() != &theElem2)
        return false;
    if (theVictim.GetTail() != &theElem3)
        return false;

    theVictim.Remove(&theElem1);

    if (theVictim.GetHead() != &theElem2)
        return false;
    if (theVictim.GetTail() != &theElem3)
        return false;

    theVictim.Remove(&theElem3);

    if (theVictim.GetHead() != &theElem2)
        return false;
    if (theVictim.GetTail() != &theElem2)
        return false;

    return true;
}   
#endif



void OSQueueIter::Next()
{
    if (fCurrentElemP == fQueueP->GetTail())
        fCurrentElemP = NULL;
    else
        fCurrentElemP = fCurrentElemP->Prev();
}


OSQueueElem* OSQueue_Blocking::DeQueueBlocking(OSThread* inCurThread, SInt32 inTimeoutInMilSecs)
{
    OSMutexLocker theLocker(&fMutex);
#ifdef __Win32_
     if (fQueue.GetLength() == 0) 
	 {	fCond.Wait(&fMutex, inTimeoutInMilSecs);
		return NULL;
	 }
#else
    if (fQueue.GetLength() == 0) 
        fCond.Wait(&fMutex, inTimeoutInMilSecs);
#endif

    OSQueueElem* retval = fQueue.DeQueue();
    return retval;
}

OSQueueElem*    OSQueue_Blocking::DeQueue()
{
    OSMutexLocker theLocker(&fMutex);
    OSQueueElem* retval = fQueue.DeQueue(); 
    return retval;
}


void OSQueue_Blocking::EnQueue(OSQueueElem* obj)
{
    {
        OSMutexLocker theLocker(&fMutex);
        fQueue.EnQueue(obj);
    }
    fCond.Signal();
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunxiaopengsun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值