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.
354 lines
7.6 KiB
354 lines
7.6 KiB
14 years ago
|
/*==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/>.
|
||
|
|
||
|
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
|
||
|
|