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.
369 lines
8.1 KiB
369 lines
8.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 |
|
|
|
|