/*==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 . 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 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 hsQueue::hsQueue( int size ) { fArraySize = size; fArray = TRACKED_NEW T[ size ]; fHead = -1; fTail = -1; fLook = -1; fEmpty = true; fFull = false; } // // Destructor. free array // template hsQueue::~hsQueue() { delete [] fArray; } // // Wrap index on increment // template void hsQueue::Inc( int *index ) { (*index) ++; if ((*index) == fArraySize) { *index = 0; } } // // Wrap index on increment // template int hsQueue::Inc( int index ) { (index) ++; if ((index) == fArraySize) { index = 0; } return index; } // // Wrap index on decrement // template void hsQueue::Dec( int *index ) { (*index) --; if ((*index) < 0) { *index = fArraySize-1; } } // // Wrap index on decrement // template int hsQueue::Dec( int index ) { (index) --; if ((index) < 0) { index = fArraySize-1; } return index; } // // Add copy of item to the array. // template hsBool hsQueue::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 hsBool hsQueue::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 hsBool hsQueue::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 hsBool hsQueue::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 hsBool hsQueue::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 #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