262 lines
6.1 KiB
C++
262 lines
6.1 KiB
C++
/*
|
|
*
|
|
* @APPLE_LICENSE_HEADER_START@
|
|
*
|
|
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
|
*
|
|
* This file contains Original Code and/or Modifications of Original Code
|
|
* as defined in and that are subject to the Apple Public Source License
|
|
* Version 2.0 (the 'License'). You may not use this file except in
|
|
* compliance with the License. Please obtain a copy of the License at
|
|
* http://www.opensource.apple.com/apsl/ and read it before using this
|
|
* file.
|
|
*
|
|
* The Original Code and all software distributed under the License are
|
|
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
* Please see the License for the specific language governing rights and
|
|
* limitations under the License.
|
|
*
|
|
* @APPLE_LICENSE_HEADER_END@
|
|
*
|
|
*/
|
|
/*
|
|
File: OSQueue.cpp
|
|
|
|
Contains: implements OSQueue class
|
|
|
|
|
|
*/
|
|
|
|
#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();
|
|
}
|