Queue();
~Queue() {}
- void init(unsigned int uiStartSize = 2, unsigned int uiSizeMultiplier = 2);
+ void init(unsigned int uiStartSize = 8, unsigned int uiSizeMultiplier = 2);
void fini();
void alloc(unsigned int uiSize);
unsigned int getLength() const;
unsigned int getSpaceNeeded(unsigned int uiSize) const;
+ // alloc helpers
+ void allocFirstTime(unsigned int uiSize);
+ void allocWhenNeeded(unsigned int uiSize);
+ void allocForce(unsigned int uiSize);
+
+ static Item* getNextHead(Item* pHead, unsigned int uiAllocated, Item* pArrayItems);
+ static Item* getPrevHead(Item* pHead, unsigned int uiAllocated, Item* pArrayItems);
+ static Item* getNextTail(Item* pTail, unsigned int uiAllocated, Item* pArrayItems);
+ static Item* getPrevTail(Item* pTail, unsigned int uiAllocated, Item* pArrayItems);
+
+ static Item* withinBounds(Item* pValue, Item* pMinBound, Item* pMaxBound);
+
+ private:
unsigned int m_uiStartSize;
unsigned int m_uiSizeMultiplier;
unsigned int m_uiAllocated;
Item* m_pArrayItems;
- bool m_fIsEmpty;
- unsigned int m_uiHead;
- unsigned int m_uiTail;
+ // NULL Head _and_ NULL Tail means empty
+ Item* m_pHead;
+ Item* m_pTail;
};
} // namespace bear
m_uiSizeMultiplier(0),
m_uiAllocated(0),
m_pArrayItems(NULL),
- m_fIsEmpty(0),
- m_uiHead(0),
- m_uiTail(0)
+ m_pHead(NULL),
+ m_pTail(NULL)
{
}
unsigned int uiSizeMultiplier
)
{
+ // Sanity checks
+ bear::DASSERT(0 < uiStartSize);
+ bear::DASSERT(1 < uiSizeMultiplier);
+
m_uiStartSize = uiStartSize;
m_uiSizeMultiplier = uiSizeMultiplier;
m_uiAllocated = 0;
- bear::DASSERT(NULL == m_pArrayItems); // this better be the case
+ // If this fires you have memory leaks
+ bear::DASSERT(NULL == m_pArrayItems);
m_pArrayItems = NULL;
- m_fIsEmpty = true;
-
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = NULL;
+ m_pTail = NULL;
}
template < class Item >
void bear::Queue<Item>::fini()
m_uiAllocated = 0;
- if(NULL != m_pArrayItems) delete m_pArrayItems;
- m_pArrayItems = NULL;
-
- m_fIsEmpty = true;
+ if(NULL != m_pArrayItems)
+ {
+ delete m_pArrayItems;
+ m_pArrayItems = NULL;
+ }
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = NULL;
+ m_pTail = NULL;
}
template < class Item >
void bear::Queue<Item>::alloc(unsigned int uiSize)
{
- if(m_uiAllocated < uiSize)
+ if(NULL == m_pArrayItems)
{
- unsigned int uiOldLength = getLength();
-
- unsigned int uiOldAllocated = m_uiAllocated;
- Item * pOldArrayItems = m_pArrayItems;
- unsigned int uiOldHead = m_uiHead;
- //unsigned int uiOldTail = m_uiTail;
-
- m_uiAllocated = 0;
- m_pArrayItems = NULL;
- m_uiHead = 0;
- m_uiTail = 0;
-
- unsigned int uiNewAllocated = uiSize;
- Item * pNewArrayItems = new Item[uiNewAllocated];
- unsigned int uiNewHead = 0;
- unsigned int uiNewTail = uiOldLength - 1;
-
- if(NULL == pOldArrayItems)
- {
- // santiy check
- bear::DASSERT(0 == uiOldLength);
- bear::DASSERT(true == m_fIsEmpty);
-
- uiNewTail = 0;
-
- // Nothing to copy over
- }
- else
- {
- // Copy old items into new array
- for(unsigned int uiNewIndex = uiNewHead; uiNewIndex <= uiNewTail; uiNewIndex++)
- {
- unsigned int uiOldIndex = mod(uiNewIndex + uiOldHead, uiOldAllocated);
- bear::DASSERT(uiOldIndex <= uiOldAllocated);
-
- bear::DASSERT(NULL != pOldArrayItems);
- pNewArrayItems[uiNewIndex] = pOldArrayItems[uiOldIndex];
- }
-
- delete pOldArrayItems;
- }
-
- m_uiAllocated = uiNewAllocated;
- m_pArrayItems = pNewArrayItems;
- m_uiHead = uiNewHead;
- m_uiTail = uiNewTail;
+ allocFirstTime(uiSize);
+ }
+ else if(m_uiAllocated < uiSize)
+ {
+ allocForce(uiSize);
}
- // TODO: return error code
+ bear::DASSERT(m_uiAllocated >= uiSize);
+
+ // TODO: return error when new fails
}
+
template < class Item >
void bear::Queue<Item>::trim()
{
- bear::DASSERT(false); // Not Implemented
+ unsigned int uiSize = getLength();
+ if(NULL == m_pArrayItems)
+ {
+ allocFirstTime(uiSize);
+ }
+ else
+ {
+ allocForce(uiSize);
+ }
+
+ // Sanity checks
+ bear::DASSERT(uiSize == getLength());
+ bear::DASSERT(uiSize == m_uiAllocated);
}
template < class Item >
bool bear::Queue<Item>::isEmpty() const
{
- return m_fIsEmpty;
+ if ( NULL == m_pHead )
+ {
+ bear::DASSERT(NULL == m_pTail);
+ return true;
+ }
+ else
+ {
+ bear::DASSERT(NULL != m_pTail);
+ return false;
+ }
}
template < class Item >
bear::DASSERT(!isEmpty());
// sanity check
- bear::DASSERT(m_uiHead <= m_uiAllocated);
+ //bear::DASSERT(m_pHead <= m_uiAllocated);
- return m_pArrayItems[m_uiHead];
+ return *m_pHead;
}
template < class Item >
bear::DASSERT(!isEmpty());
// sanity check
- bear::DASSERT(m_uiTail <= m_uiAllocated);
+ //bear::DASSERT(m_pTail <= m_uiAllocated);
- return m_pArrayItems[m_uiTail];
+ return *m_pTail;
}
template < class Item >
void bear::Queue<Item>::pushFront(const Item& i)
{
// Make sure we have the space to add an item
- alloc( getSpaceNeeded( getLength() + 1 ) );
+ allocWhenNeeded( getLength() + 1 );
if(isEmpty())
{
- m_fIsEmpty = false;
-
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = m_pArrayItems;
+ m_pTail = m_pArrayItems;
}
else
{
- m_uiHead = mod( m_uiHead - 1, m_uiAllocated );
+ m_pHead = getNextHead(m_pHead, m_uiAllocated, m_pArrayItems);
}
- m_pArrayItems[m_uiHead] = i;
+ *m_pHead = i;
}
template < class Item >
void bear::Queue<Item>::pushBack(const Item& i)
{
// Make sure we have the space to add an item
- alloc( getSpaceNeeded( getLength() + 1 ) );
+ allocWhenNeeded( getLength() + 1 );
if(isEmpty())
{
- m_fIsEmpty = false;
-
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = m_pArrayItems;
+ m_pTail = m_pArrayItems;
}
else
{
- m_uiTail = mod( m_uiTail + 1, m_uiAllocated );
+ m_pTail = getNextTail(m_pTail, m_uiAllocated, m_pArrayItems);
}
- m_pArrayItems[m_uiTail] = i;
+ *m_pTail = i;
}
template < class Item >
{
bear::DASSERT(!isEmpty());
- if( m_uiHead == m_uiTail )
+ if( m_pHead == m_pTail )
{
- m_fIsEmpty = true;
-
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = NULL;
+ m_pTail = NULL;
}
else
{
- m_uiHead = mod( m_uiHead + 1, m_uiAllocated );
+ m_pHead = getPrevHead(m_pHead, m_uiAllocated, m_pArrayItems);
}
}
{
bear::DASSERT(!isEmpty());
- if( m_uiHead == m_uiTail )
+ if( m_pHead == m_pTail )
{
- m_fIsEmpty = true;
-
- m_uiHead = 0;
- m_uiTail = 0;
+ m_pHead = NULL;
+ m_pTail = NULL;
}
else
{
- m_uiTail = mod( m_uiTail - 1, m_uiAllocated );
+ m_pTail = getPrevTail(m_pTail, m_uiAllocated, m_pArrayItems);
}
}
}
else
{
- return mod( m_uiTail - m_uiHead, m_uiAllocated ) + 1;
+ return mod( m_pTail - m_pHead, m_uiAllocated ) + 1;
}
}
template < class Item >
-unsigned int bear::Queue<Item>::getSpaceNeeded(unsigned int uiSize) const
+void bear::Queue<Item>::allocFirstTime(unsigned int uiSize)
{
- unsigned int uiNewSize = m_uiAllocated;
+ // santiy checks
+ bear::DASSERT(0 == m_uiAllocated);
+ bear::DASSERT(NULL == m_pArrayItems);
+ bear::DASSERT(isEmpty());
- if(0 == uiNewSize)
+ if(0 < uiSize)
{
- uiNewSize = m_uiStartSize;
+ unsigned int uiNewAllocated = uiSize;
+ Item * pNewArrayItems = new Item[uiNewAllocated];
+
+ m_uiAllocated = uiNewAllocated;
+ m_pArrayItems = pNewArrayItems;
}
+}
+
+template < class Item >
+void bear::Queue<Item>::allocWhenNeeded(unsigned int uiSize)
+{
+ unsigned int uiSizeNeeded = (0 == m_uiAllocated) ? m_uiStartSize : m_uiAllocated;
+
+ bear::DASSERT(0 < m_uiStartSize);
+ bear::DASSERT(1 < m_uiSizeMultiplier);
- while ( uiNewSize < uiSize )
+ while ( uiSizeNeeded < uiSize )
{
- uiNewSize *= m_uiSizeMultiplier;
+ uiSizeNeeded *= m_uiSizeMultiplier;
}
- return uiNewSize;
+ if(uiSizeNeeded > m_uiAllocated)
+ {
+ alloc(uiSizeNeeded);
+ }
+}
+
+template < class Item >
+void bear::Queue<Item>::allocForce(unsigned int uiSize)
+{
+ unsigned int uiOldLength = getLength();
+
+ unsigned int uiOldAllocated = m_uiAllocated;
+ Item * pOldArrayItems = m_pArrayItems;
+ Item * pOldHead = m_pHead;
+ Item * pOldTail = m_pTail;
+
+ m_uiAllocated = 0;
+ m_pArrayItems = NULL;
+ m_pHead = 0;
+ m_pTail = 0;
+
+ unsigned int uiNewAllocated = uiSize;
+ Item * pNewArrayItems = new Item[uiNewAllocated];
+ Item * pNewHead = pNewArrayItems;
+ Item * pNewTail = pNewHead + uiOldLength - 1;
+
+ {
+ // Copy old items into new array
+ Item * pNewItem = pNewHead;
+ Item * pOldItem = pOldHead;
+
+ for( unsigned int ii = 0; ii < uiOldLength; ii++ )
+ {
+ *pNewItem = *pOldItem;
+
+ // Pick next item
+ pNewItem = getNextTail(pNewItem, uiNewAllocated, pNewArrayItems);
+ pOldItem = getNextTail(pOldItem, uiOldAllocated, pOldArrayItems);
+ }
+
+ // santiy checks
+ bear::DASSERT(pNewTail == getPrevTail(pNewItem, uiNewAllocated, pNewArrayItems));
+ bear::DASSERT(pOldTail == getPrevTail(pOldItem, uiOldAllocated, pOldArrayItems));
+
+ delete pOldArrayItems;
+ pOldArrayItems = NULL;
+ }
+
+ m_uiAllocated = uiNewAllocated;
+ m_pArrayItems = pNewArrayItems;
+ m_pHead = pNewHead;
+ m_pTail = pNewTail;
+}
+
+
+template < class Item >
+Item* bear::Queue<Item>::getNextHead
+(
+ Item* pHead,
+ unsigned int uiAllocated,
+ Item* pArrayItems
+)
+{
+ return withinBounds( pHead - 1, pArrayItems, pArrayItems + uiAllocated );
+}
+
+template < class Item >
+Item* bear::Queue<Item>::getPrevHead
+(
+ Item* pHead,
+ unsigned int uiAllocated,
+ Item* pArrayItems
+)
+{
+ return withinBounds( pHead + 1, pArrayItems, pArrayItems + uiAllocated );
+}
+
+template < class Item >
+Item* bear::Queue<Item>::getNextTail
+(
+ Item* pTail,
+ unsigned int uiAllocated,
+ Item* pArrayItems
+)
+{
+ return withinBounds( pTail + 1, pArrayItems, pArrayItems + uiAllocated );
+}
+
+template < class Item >
+Item* bear::Queue<Item>::getPrevTail
+(
+ Item* pTail,
+ unsigned int uiAllocated,
+ Item* pArrayItems
+)
+{
+ return withinBounds( pTail - 1, pArrayItems, pArrayItems + uiAllocated );
+}
+
+template < class Item >
+Item* bear::Queue<Item>::withinBounds
+(
+ Item* pValue,
+ Item* pMinBound,
+ Item* pMaxBound
+)
+{
+ unsigned int uiValue = reinterpret_cast<unsigned int>( pValue );
+ unsigned int uiMinBound = reinterpret_cast<unsigned int>( pMinBound );
+ unsigned int uiMaxBound = reinterpret_cast<unsigned int>( pMaxBound );
+
+ unsigned int uiBoundedValue = uiMinBound + mod(uiValue - uiMinBound, uiMaxBound - uiMinBound);
+
+ Item* pBoundedValue = reinterpret_cast<Item*>(uiBoundedValue);
+
+ // sanity checks
+ bear::DASSERT(pMinBound <= pBoundedValue);
+ bear::DASSERT(pMaxBound > pBoundedValue);
+
+ return pBoundedValue;
}