// // File: hzTmplQue.h // // Legal Notice: This file is part of the HadronZoo C++ Class Library. // // Copyright 2025 HadronZoo Project (http://www.hadronzoo.com) // // The HadronZoo C++ Class Library is free software: You can redistribute it, and/or modify it under the terms of the GNU Lesser General Public License, as published by the Free // Software Foundation, either version 3 of the License, or any later version. // // The HadronZoo C++ Class Library 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 Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License along with the HadronZoo C++ Class Library. If not, see http://www.gnu.org/licenses. //
#ifndef hzTmplQue_h #define hzTmplQue_h
#include "hzString.h" #include "hzLock.h" #include "hzProcess.h"
/* ** Prototypes */
void Fatal (const char* va_alist ...) ;
template <class OBJ> class _hz_queitem { // Category: Collection Support // // List element containing an element and a pointer to the next element. For use in the unordered list class templates, hzList, hzQue and hzStack.
public: _hz_queitem* next ; // Next item in list OBJ m_Obj ; // Object in list
_hz_queitem (OBJ obj) { next = 0 ; m_Obj = obj ; } } ;
template <class OBJ> class hzQue { // Category: Object Collection // // The hzQue class template faciliates a memory resident que of objects. A que is characterized by PUSH and POP operations in which new // objects are injected at the back of the que (pushed) and objects are removed from the front of the que (pulled).
private: struct _que_ca { // Struct to hold actual content (avoid hard copying)
_hz_queitem<OBJ>* m_pList ; // Start of que _hz_queitem<OBJ>* m_pLast ; // End of que hzLocker* m_pLock ; // Locking (off by default) hzString m_Name ; // Diagnostics & reports uint32_t m_nCount ; // Population _mut uint32_t m_nCopy ; // Copy count OBJ m_Default ; // Default (null) element
_que_ca (void) { memset(&m_Default, 0, sizeof(OBJ)) ; m_pList = m_pLast = 0 ; m_pLock = 0 ; m_nCount = m_nCopy = 0 ; } ~_que_ca (void) {}
void SetLock (hzLockOpt eLock) { if (eLock == HZ_ATOMIC) m_pLock = new hzLockRW() ; if (eLock == HZ_MUTEX) m_pLock = new hzLockRWD() ; }
void LockRead (void) { if (m_pLock) m_pLock->LockRead() ; } void LockWrite (void) { if (m_pLock) m_pLock->LockWrite() ; } void Unlock (void) { if (m_pLock) m_pLock->Unlock() ; } } ;
_que_ca* mx ; // Pointer to internal content
// Prevent copies hzQue<OBJ> (const hzQue<OBJ>&) ; hzQue<OBJ>& operator= (const hzQue<OBJ>&) ;
public: // Constructors hzQue (hzLockOpt eLock = HZ_NOLOCK) { mx = new _que_ca() ; mx->SetLock(eLock) ; } hzQue (const hzString name) { mx = new _que_ca() ; mx->m_Name = name ; mx->SetLock(HZ_MUTEX) ; }
// Destructor ~hzQue (void) { if (mx->m_nCopy > 0) mx->m_nCopy-- ; else { Clear() ; delete mx ; mx = 0 ; } }
void Clear (void) { _hz_queitem<OBJ>* pC ; // Curreent list item _hz_queitem<OBJ>* pN ; // Next list item
for (pC = mx->m_pList ; pC ; pC = pN) { pN = pC->next ; delete pC ; }
mx->m_pList = mx->m_pLast = 0 ; mx->m_nCount = 0 ; }
// Assignment operator /* const hzQue<OBJ>& operator= (const hzQue<OBJ>& op) { // If this control area is the same as that of the operand, do nothing. Otherwise decouple from or clear the control area and adopt that of the operand. if (mx == op.mx) return *this ;
// If there is an existing list, clear it. if (mx->m_nCopy) mx->m_nCopy-- ; else mx->Clear() ;
mx = op.mx ; mx->m_nCopy++ ; return *this ; } */
uint32_t Count (void) { // Return the number of items in the queue return mx->m_nCount ; }
hzEcode Push (const OBJ& obj) { // Push supplied object onto the queue
_hz_queitem<OBJ>* pTL ; // List item to accomodate new object
if (!(pTL = new _hz_queitem<OBJ>(obj))) Fatal("Could not allocate new que element") ;
if (mx->m_pList == 0) mx->m_pList = mx->m_pLast = pTL ; else { //mx->m_pLast->m_pNext = pTL ; mx->m_pLast->next = pTL ; mx->m_pLast = pTL ; }
mx->m_nCount++ ; return E_OK ; }
OBJ& Pull (void) { // Pull an object from the queue
_hz_queitem<OBJ>* pTL ; // Object-link iterator
OBJ obj ; // Current object-link
if ((pTL = mx->m_pList)) { obj = mx->m_pList->m_Obj ; //mx->m_pList = mx->m_pList->m_pNext ; mx->m_pList = mx->m_pList->next ; delete pTL ; mx->m_nCount-- ; }
return mx->m_Default ; }
hzEcode Delete (const OBJ& obj) { // Delete the supplied object from the queue (on condition it is foundin the queue)
_hz_queitem<OBJ>* pTL ; // Current link _hz_queitem<OBJ>* pPL ; // Previous link
hzEcode rc = E_NOTFOUND ; // Return code
// match obj pointer to one on list
pPL = 0 ; for (pTL = mx->m_pList ; pTL ; pTL = pTL->m_pNext) { if (pTL->m_Obj == obj) { // found item to delete if (pTL == mx->m_pList) //mx->m_pList = mx->m_pList->m_pNext ; mx->m_pList = mx->m_pList->next ;
// If the item is the last if (pTL == mx->m_pLast) mx->m_pLast = pPL ;
// tie adjacent items together if (pPL) //pPL->m_pNext = pTL->m_pNext; pPL->next = pTL->next;
delete pTL ; mx->m_nCount-- ; rc = E_OK ; break ; }
pPL = pTL ; }
return rc ; } } ;
#endif // hzTmplQue_h