LargeStack.h 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. template <class T>
  6. struct LargeStackBlock {
  7. T* items;
  8. int index;
  9. int itemCount;
  10. static LargeStackBlock<T>* Make(ArenaAllocator* alloc,int itemCount) {
  11. LargeStackBlock<T>* block = AnewStruct(alloc, LargeStackBlock<T>);
  12. block->itemCount=itemCount;
  13. block->items = AnewArray(alloc, T, itemCount);
  14. block->index=0;
  15. return block;
  16. }
  17. BOOL Full() { return index>=itemCount; }
  18. BOOL Empty() { return index==0; }
  19. void Push(T item) {
  20. AssertMsg(!Full(),"can't push to full stack block");
  21. items[index++]=item;
  22. }
  23. T Pop() {
  24. AssertMsg(!Empty(),"can't pop empty stack block");
  25. index--;
  26. return items[index];
  27. }
  28. };
  29. template <class T>
  30. class LargeStack {
  31. SList<LargeStackBlock<T>*>* blockStack;
  32. static const int BlockSize=8;
  33. static const int GrowSize=128;
  34. ArenaAllocator* alloc;
  35. LargeStack(ArenaAllocator* alloc) : alloc(alloc) {
  36. blockStack=Anew(alloc,SList<LargeStackBlock<T>*>,alloc);
  37. blockStack->Push(LargeStackBlock<T>::Make(alloc,BlockSize));
  38. }
  39. public:
  40. static LargeStack * New(ArenaAllocator* alloc)
  41. {
  42. return Anew(alloc, LargeStack, alloc);
  43. }
  44. void Push(T item) {
  45. LargeStackBlock<T>* top=blockStack->Top();
  46. if (top->Full()) {
  47. top=LargeStackBlock<T>::Make(alloc,top->itemCount+GrowSize);
  48. blockStack->Push(top);
  49. }
  50. top->Push(item);
  51. }
  52. BOOL Empty() {
  53. LargeStackBlock<T>* top=blockStack->Top();
  54. if (top->Empty()) {
  55. if (blockStack->HasOne()) {
  56. // Avoid popping the last empty block to reduce freelist overhead.
  57. return true;
  58. }
  59. blockStack->Pop();
  60. return blockStack->Empty();
  61. }
  62. else return false;
  63. }
  64. T Pop() {
  65. LargeStackBlock<T>* top=blockStack->Top();
  66. if (top->Empty()) {
  67. blockStack->Pop();
  68. AssertMsg(!blockStack->Empty(),"can't pop empty block stack");
  69. top=blockStack->Top();
  70. }
  71. return top->Pop();
  72. }
  73. };