Proto  3.2
Proto_Stack.H
Go to the documentation of this file.
1 #ifndef _PROTO_STACK_H_
2 #define _PROTO_STACK_H_
3 
4 #include <memory>
5 #include <stack>
6 #include "Proto_PAssert.H"
7 #include "Proto_MemType.H"
8 #include "Proto_Macros.H"
9 #include "Proto_Memory.H" //unused, but should be used instead of macros
10 
11 #define PR_STACK_ALLOC 4294967296 //4GB
12 //#define PR_STACK_OVERFLOW 268435456 //256MB
13 #define PR_STACK_OVERFLOW 536870912 //512MB
14 namespace Proto {
15 
16  template<MemType MEM = MEMTYPE_DEFAULT>
17  class Stack
18  {
19  public:
20 
21  /// Get Stack Singleton
22  static Stack<MEM>& getStack()
23  {
24  static Stack<MEM> s_stack(PR_STACK_ALLOC);
25  return s_stack;
26  }
27 
28  /// Constructor
29  inline Stack(size_t a_capacity)
30  {
31  protoMalloc(MEM, m_stack, a_capacity);
32  m_top = m_stack;
33  m_capacity = a_capacity;
34  m_hasOverflow = false;
35  m_useStack = false;
36  }
37 
38  /// Destructor
39  inline ~Stack()
40  {
41  protoFree(MEM, m_stack);
42  }
43 
44  /// Public Allocate
45  inline void* alloc(size_t a_sz)
46  {
47  PROTO_ASSERT(a_sz > 0,
48  "Stack::alloc | Error: Tried to allocate an array of size 0 to Stack.");
50  "Stack::alloc | Error: Tried to use the stack when it is not turned on. Did you forget to call PR_STACK_ON?");
51 #ifdef PROTO_ACCEL
52  const size_t align = 256;
53  size_t increment = align*((a_sz+align-1)/align);
54 #else
55  size_t increment = a_sz;
56 #endif
57  if (m_useStack)
58  {
59  return doAlloc(increment);
60  } else {
61  return NULL;
62  }
63  }
64 
65  /// Toggle Stack
66  inline void toggleStack(bool a_flag)
67  {
68  PROTO_ASSERT(a_flag != m_useStack,
69  "Stack::toggleStack | Error: Toggling stack usage to %d when it is already %d. Did you forget to call PR_STACK_OFF?", a_flag, m_useStack);
70  m_useStack = a_flag;
71  if (!a_flag) { freeStack(); }
72  }
73 
74  /// Query Stack Active
75  inline bool enabled()
76  {
77  return m_useStack;
78  }
79 
80  /// Query Unused
81  inline size_t unused()
82  {
83  size_t u = m_top - m_stack;
84  if (m_hasOverflow)
85  {
86  return (m_capacity - u) + m_overflow->unused();
87  } else {
88  return (m_capacity - u);
89  }
90  }
91 
92  /// Query Unused
93  inline size_t used()
94  {
95  size_t u = m_top - m_stack;
96  if (m_hasOverflow)
97  {
98  return m_overflow->used() + u;
99  } else {
100  return u;
101  }
102  }
103 
104  private:
105 
106  /// Private Allocate
107  inline void* doAlloc(size_t a_increment)
108  {
109  if (m_top + a_increment - m_stack < m_capacity)
110  {
111  void* rtn = (void*)(m_top);
112  m_top += a_increment;
113  m_increments.push(a_increment);
114  return rtn;
115  } else {
116  if (m_hasOverflow)
117  {
118  return m_overflow->doAlloc(a_increment);
119  } else {
120  m_overflow = std::make_shared<Stack<MEM>>(PR_STACK_OVERFLOW);
121  m_hasOverflow = true;
122  return m_overflow->doAlloc(a_increment);
123  }
124  }
125  }
126 
127  /// Free Stack
128  inline void freeStack()
129  {
130  if (m_hasOverflow)
131  {
132  m_overflow->freeStack();
133  }
134  while(!m_increments.empty())
135  {
136  m_increments.pop();
137  }
138  m_top = m_stack;
139  }
140 
141 
143  char* m_stack;
144  char* m_top;
145  size_t m_capacity;
146  std::stack<size_t> m_increments;
149  std::shared_ptr<Stack<MEM>> m_overflow;
150 
151  }; // end class Stack
152 
153 #define PR_STACK_ON Stack<MEMTYPE_DEFAULT>::getStack().toggleStack(true);
154 #define PR_STACK_OFF Stack<MEMTYPE_DEFAULT>::getStack().toggleStack(false);
155 
156 } // end namespace Proto
157 #endif // end include guard
void * alloc(size_t a_sz)
Public Allocate.
Definition: Proto_Stack.H:45
std::shared_ptr< Stack< MEM > > m_overflow
Definition: Proto_Stack.H:149
char * m_stack
Definition: Proto_Stack.H:143
static Stack< MEM > & getStack()
Get Stack Singleton.
Definition: Proto_Stack.H:22
size_t used()
Query Unused.
Definition: Proto_Stack.H:93
#define PR_STACK_ALLOC
Definition: Proto_Stack.H:11
#define protoFree(memtype, PTR)
Definition: Proto_Macros.H:22
char * m_top
Definition: Proto_Stack.H:144
void freeStack()
Free Stack.
Definition: Proto_Stack.H:128
#define protoMalloc(memtype, PTR, NBYTES)
Definition: Proto_Macros.H:21
Definition: Proto_Stack.H:17
bool enabled()
Query Stack Active.
Definition: Proto_Stack.H:75
#define PROTO_ASSERT(stmt, args...)
Definition: Proto_PAssert.H:48
std::stack< size_t > m_increments
Definition: Proto_Stack.H:146
size_t m_capacity
Definition: Proto_Stack.H:145
Stack(size_t a_capacity)
Constructor.
Definition: Proto_Stack.H:29
Definition: Proto_Array.H:17
int m_bufferIndex
Definition: Proto_Stack.H:147
void toggleStack(bool a_flag)
Toggle Stack.
Definition: Proto_Stack.H:66
~Stack()
Destructor.
Definition: Proto_Stack.H:39
#define PR_STACK_OVERFLOW
Definition: Proto_Stack.H:13
bool m_useStack
Definition: Proto_Stack.H:142
void * doAlloc(size_t a_increment)
Private Allocate.
Definition: Proto_Stack.H:107
bool m_hasOverflow
Definition: Proto_Stack.H:148
size_t unused()
Query Unused.
Definition: Proto_Stack.H:81