blob: e1f3828aa032751ea88cfece25362dbb85704f3c [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
template <class T>
struct LargeStackBlock {
T* items;
int index;
int itemCount;
static LargeStackBlock<T>* Make(ArenaAllocator* alloc,int itemCount) {
LargeStackBlock<T>* block = AnewStruct(alloc, LargeStackBlock<T>);
block->itemCount=itemCount;
block->items = AnewArray(alloc, T, itemCount);
block->index=0;
return block;
}
BOOL Full() { return index>=itemCount; }
BOOL Empty() { return index==0; }
void Push(T item) {
AssertMsg(!Full(),"can't push to full stack block");
items[index++]=item;
}
T Pop() {
AssertMsg(!Empty(),"can't pop empty stack block");
index--;
return items[index];
}
};
template <class T>
class LargeStack {
SList<LargeStackBlock<T>*>* blockStack;
static const int BlockSize=8;
static const int GrowSize=128;
ArenaAllocator* alloc;
LargeStack(ArenaAllocator* alloc) : alloc(alloc) {
blockStack=Anew(alloc,SList<LargeStackBlock<T>*>,alloc);
blockStack->Push(LargeStackBlock<T>::Make(alloc,BlockSize));
}
public:
static LargeStack * New(ArenaAllocator* alloc)
{
return Anew(alloc, LargeStack, alloc);
}
void Push(T item) {
LargeStackBlock<T>* top=blockStack->Top();
if (top->Full()) {
top=LargeStackBlock<T>::Make(alloc,top->itemCount+GrowSize);
blockStack->Push(top);
}
top->Push(item);
}
BOOL Empty() {
LargeStackBlock<T>* top=blockStack->Top();
if (top->Empty()) {
if (blockStack->HasOne()) {
// Avoid popping the last empty block to reduce freelist overhead.
return true;
}
blockStack->Pop();
return blockStack->Empty();
}
else return false;
}
T Pop() {
LargeStackBlock<T>* top=blockStack->Top();
if (top->Empty()) {
blockStack->Pop();
AssertMsg(!blockStack->Empty(),"can't pop empty block stack");
top=blockStack->Top();
}
return top->Pop();
}
};