OSQueue用法

来源:互联网 发布:windows xp 64位原版 编辑:程序博客网 时间:2024/06/05 16:42

#ifndef _OSQUEUE_H_#define _OSQUEUE_H_#include "MyAssert.h"#include "OSHeaders.h"#include "OSMutex.h"#include "OSCond.h"#include "OSThread.h"#define OSQUEUETESTING 0class 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 OSQUEUETESTINGBool16 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;}   #endifvoid 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();}



0 0
原创粉丝点击