You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
9.1 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef hsQueue_Defined
#define hsQueue_Defined
#include "hsTypes.h"
template <class T> class hsQueue {
private:
int fArraySize;
T *fArray;
int fHead; // Index of first element in the queue
int fTail; // Index of next free spot in the queue
int fLook; // Index of look pointer
hsBool fFull; // Is queue full?
hsBool fEmpty; // Is queue empty?
void Inc(int *index);
int Inc(int index);
void Dec(int *index);
int Dec(int index);
public:
hsQueue( int size );
~hsQueue();
hsBool Append(const T &newTail); // Add to end of line
hsBool Remove(const T &someElement); // Find and remove element in the line
hsBool Pop(T *headElement); // Remove and return the head of the line
hsBool StartLook(T *headElement); // Return the head of the line w/out removing it
hsBool NextLook(T *nextElement); // Return the head of the line w/out removing it
hsBool IsEmpty(void) { return fEmpty; }
hsBool IsFull(void) { return fFull; }
};
//
// Constructor
// Allocate array, init head/tail indices
//
template <class T> hsQueue<T>::hsQueue( int size )
{
fArraySize = size;
fArray = TRACKED_NEW T[ size ];
fHead = -1;
fTail = -1;
fLook = -1;
fEmpty = true;
fFull = false;
}
//
// Destructor. free array
//
template <class T> hsQueue<T>::~hsQueue()
{
delete [] fArray;
}
//
// Wrap index on increment
//
template <class T> void hsQueue<T>::Inc( int *index )
{
(*index) ++;
if ((*index) == fArraySize) {
*index = 0;
}
}
//
// Wrap index on increment
//
template <class T> int hsQueue<T>::Inc( int index )
{
(index) ++;
if ((index) == fArraySize) {
index = 0;
}
return index;
}
//
// Wrap index on decrement
//
template <class T> void hsQueue<T>::Dec( int *index )
{
(*index) --;
if ((*index) < 0) {
*index = fArraySize-1;
}
}
//
// Wrap index on decrement
//
template <class T> int hsQueue<T>::Dec( int index )
{
(index) --;
if ((index) < 0) {
index = fArraySize-1;
}
return index;
}
//
// Add copy of item to the array.
//
template <class T> hsBool hsQueue<T>::Append(const T &thing)
{
if (fHead == -1 && fTail == -1) {
// init case
fHead = 0;
fTail = 0;
}
if (fFull) {
// Queue is full
return false;
}
if ( (fHead<0 || fHead>=fArraySize) ) {
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Append: Illegal head pointer", fHead);
}
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Append: Illegal tail pointer", fTail);
// Copy
fArray[fTail] = thing;
fEmpty = false;
// increment tail pointer
Inc(&fTail);
if (fTail == fHead) {
fFull = true;
}
return true;
}
//
// Get a copy of the head of the array
//
template <class T> hsBool hsQueue<T>::Pop(T *thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Pop: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Pop: Illegal tail pointer", fTail);
// Copy
*thing = fArray[fHead];
fFull = false;
// Increment head pointer
Inc(&fHead);
if (fHead == fTail) {
fEmpty = true;
}
return true;
}
//
// Remove item from list
//
template <class T> hsBool hsQueue<T>::Remove(const T &thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "Remove: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "Remove: Illegal tail pointer", fTail);
// loop through list, find item
int i = fHead;
do {
if (fArray[i] == thing) {
// Found it - now remove it by sliding everything down 1
int j=Inc(i);
while(j!= fTail) {
if (fLook==j)
Dec(&fLook);
fArray[Dec(j)] = fArray[j];
Inc(&j);
}
if (fLook==fTail)
Dec(&fLook);
Dec(&fTail);
if (fTail == fHead) {
fEmpty = true;
}
return true;
}
Inc(&i);
if (i==fTail) {
return false;
}
} while(true);
}
//
// Return pointer to first item in list, without popping it.
// Return false if nothing there.
//
template <class T> hsBool hsQueue<T>::StartLook(T *thing)
{
if (fEmpty) {
return false;
}
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "StartLook: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "StartLook: Illegal tail pointer", fTail);
fLook = fHead;
*thing = fArray[fLook];
// inc look pointer
Inc(&fLook);
// success
return true;
}
//
// Return pointer to next item in list, without popping it. Doesn't change head or tail.
// Should be called immediately after StartLook.
// Return false when at end of list.
//
template <class T> hsBool hsQueue<T>::NextLook(T *thing)
{
if (fEmpty || fLook == fTail) {
return false;
}
hsAssert(fLook != -1, "Must call StartLook first\n");
hsIfDebugMessage( (fHead<0 || fHead>=fArraySize), "NextLook: Illegal head pointer", fHead);
hsIfDebugMessage( (fTail<0 || fTail>=fArraySize), "NextLook: Illegal tail pointer", fTail);
// Return copy of item without removing it
*thing = fArray[fLook];
Inc(&fLook);
return true;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// Code for threaded message queues - move to another file
//
#ifdef MQUEUE
#include "hsThread.h"
#if HS_BUILD_FOR_UNIX
#include <mqueue.h>
#endif
class hsListQue {
public:
struct Elem {
Elem* fNext;
};
private:
Elem* fHead;
Elem* fTail;
int fCount;
public:
hsListQue();
virtual ~hsListQue();
virtual int Count();
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue();
};
class hsMutexQueue : public hsListQue {
hsMutex fMutex;
public:
hsMutexQueue() {}
virtual int Count();
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue(); // will return nil if the queue is empty
};
class hsSemaphoreQueue : public hsMutexQueue {
hsSemaphore fSema;
public:
hsSemaphoreQueue() {}
virtual void Enqueue(Elem* newItem);
virtual Elem* Dequeue(); // never returns nil, it just waits
};
class hsMsgQueue {
int fMaxSize;
#if HS_BUILD_FOR_UNIX
mqd_t fMQ;
#else
class hsPrivateMQ* fMQ;
UInt32 fAccess;
#endif
public:
enum {
kRead = 0x0001,
kWrite = 0x0002,
kBlock = 0x0004
};
hsMsgQueue();
virtual ~hsMsgQueue();
hsBool Create(const char name[], int maxSize, UInt32 access);
hsBool Open(const char name[], UInt32 access);
void Close();
int GetMaxSize() const { return fMaxSize; }
hsBool Send(const void* data, int size = 0);
int Receive(void* data); // returns actual size or 0
static void Delete(const char name[]);
};
#endif // MQUEUE
#endif