src/share/vm/utilities/stack.hpp

changeset 3900
d2a62e0f25eb
parent 2314
f95d63e2154a
child 4153
b9a9ed0f8eeb
equal deleted inserted replaced
3877:74533f63b116 3900:d2a62e0f25eb
23 */ 23 */
24 24
25 #ifndef SHARE_VM_UTILITIES_STACK_HPP 25 #ifndef SHARE_VM_UTILITIES_STACK_HPP
26 #define SHARE_VM_UTILITIES_STACK_HPP 26 #define SHARE_VM_UTILITIES_STACK_HPP
27 27
28 #include "memory/allocation.hpp"
28 #include "memory/allocation.inline.hpp" 29 #include "memory/allocation.inline.hpp"
29 30
30 // Class Stack (below) grows and shrinks by linking together "segments" which 31 // Class Stack (below) grows and shrinks by linking together "segments" which
31 // are allocated on demand. Segments are arrays of the element type (E) plus an 32 // are allocated on demand. Segments are arrays of the element type (E) plus an
32 // extra pointer-sized field to store the segment link. Recently emptied 33 // extra pointer-sized field to store the segment link. Recently emptied
49 // 50 //
50 // The alloc() method must return storage aligned for any use. The 51 // The alloc() method must return storage aligned for any use. The
51 // implementation in class Stack assumes that alloc() will terminate the process 52 // implementation in class Stack assumes that alloc() will terminate the process
52 // if the allocation fails. 53 // if the allocation fails.
53 54
54 template <class E> class StackIterator; 55 template <class E, MEMFLAGS F> class StackIterator;
55 56
56 // StackBase holds common data/methods that don't depend on the element type, 57 // StackBase holds common data/methods that don't depend on the element type,
57 // factored out to reduce template code duplication. 58 // factored out to reduce template code duplication.
58 class StackBase 59 template <MEMFLAGS F> class StackBase
59 { 60 {
60 public: 61 public:
61 size_t segment_size() const { return _seg_size; } // Elements per segment. 62 size_t segment_size() const { return _seg_size; } // Elements per segment.
62 size_t max_size() const { return _max_size; } // Max elements allowed. 63 size_t max_size() const { return _max_size; } // Max elements allowed.
63 size_t max_cache_size() const { return _max_cache_size; } // Max segments 64 size_t max_cache_size() const { return _max_cache_size; } // Max segments
87 88
88 #ifdef __GNUC__ 89 #ifdef __GNUC__
89 #define inline 90 #define inline
90 #endif // __GNUC__ 91 #endif // __GNUC__
91 92
92 template <class E> 93 template <class E, MEMFLAGS F>
93 class Stack: public StackBase 94 class Stack: public StackBase<F>
94 { 95 {
95 public: 96 public:
96 friend class StackIterator<E>; 97 friend class StackIterator<E, F>;
97 98
98 // segment_size: number of items per segment 99 // segment_size: number of items per segment
99 // max_cache_size: maxmium number of *segments* to cache 100 // max_cache_size: maxmium number of *segments* to cache
100 // max_size: maximum number of items allowed, rounded to a multiple of 101 // max_size: maximum number of items allowed, rounded to a multiple of
101 // the segment size (0 == unlimited) 102 // the segment size (0 == unlimited)
102 inline Stack(size_t segment_size = default_segment_size(), 103 inline Stack(size_t segment_size = default_segment_size(),
103 size_t max_cache_size = 4, size_t max_size = 0); 104 size_t max_cache_size = 4, size_t max_size = 0);
104 inline ~Stack() { clear(true); } 105 inline ~Stack() { clear(true); }
105 106
106 inline bool is_empty() const { return _cur_seg == NULL; } 107 inline bool is_empty() const { return this->_cur_seg == NULL; }
107 inline bool is_full() const { return _full_seg_size >= max_size(); } 108 inline bool is_full() const { return this->_full_seg_size >= this->max_size(); }
108 109
109 // Performance sensitive code should use is_empty() instead of size() == 0 and 110 // Performance sensitive code should use is_empty() instead of size() == 0 and
110 // is_full() instead of size() == max_size(). Using a conditional here allows 111 // is_full() instead of size() == max_size(). Using a conditional here allows
111 // just one var to be updated when pushing/popping elements instead of two; 112 // just one var to be updated when pushing/popping elements instead of two;
112 // _full_seg_size is updated only when pushing/popping segments. 113 // _full_seg_size is updated only when pushing/popping segments.
113 inline size_t size() const { 114 inline size_t size() const {
114 return is_empty() ? 0 : _full_seg_size + _cur_seg_size; 115 return is_empty() ? 0 : this->_full_seg_size + this->_cur_seg_size;
115 } 116 }
116 117
117 inline void push(E elem); 118 inline void push(E elem);
118 inline E pop(); 119 inline E pop();
119 120
159 private: 160 private:
160 E* _cur_seg; // Current segment. 161 E* _cur_seg; // Current segment.
161 E* _cache; // Segment cache to avoid ping-ponging. 162 E* _cache; // Segment cache to avoid ping-ponging.
162 }; 163 };
163 164
164 template <class E> class ResourceStack: public Stack<E>, public ResourceObj 165 template <class E, MEMFLAGS F> class ResourceStack: public Stack<E, F>, public ResourceObj
165 { 166 {
166 public: 167 public:
167 // If this class becomes widely used, it may make sense to save the Thread 168 // If this class becomes widely used, it may make sense to save the Thread
168 // and use it when allocating segments. 169 // and use it when allocating segments.
169 ResourceStack(size_t segment_size = Stack<E>::default_segment_size()): 170 // ResourceStack(size_t segment_size = Stack<E, F>::default_segment_size()):
170 Stack<E>(segment_size, max_uintx) 171 ResourceStack(size_t segment_size): Stack<E, F>(segment_size, max_uintx)
171 { } 172 { }
172 173
173 // Set the segment pointers to NULL so the parent dtor does not free them; 174 // Set the segment pointers to NULL so the parent dtor does not free them;
174 // that must be done by the ResourceMark code. 175 // that must be done by the ResourceMark code.
175 ~ResourceStack() { Stack<E>::reset(true); } 176 ~ResourceStack() { Stack<E, F>::reset(true); }
176 177
177 protected: 178 protected:
178 virtual E* alloc(size_t bytes); 179 virtual E* alloc(size_t bytes);
179 virtual void free(E* addr, size_t bytes); 180 virtual void free(E* addr, size_t bytes);
180 181
181 private: 182 private:
182 void clear(bool clear_cache = false); 183 void clear(bool clear_cache = false);
183 }; 184 };
184 185
185 template <class E> 186 template <class E, MEMFLAGS F>
186 class StackIterator: public StackObj 187 class StackIterator: public StackObj
187 { 188 {
188 public: 189 public:
189 StackIterator(Stack<E>& stack): _stack(stack) { sync(); } 190 StackIterator(Stack<E, F>& stack): _stack(stack) { sync(); }
190 191
191 Stack<E>& stack() const { return _stack; } 192 Stack<E, F>& stack() const { return _stack; }
192 193
193 bool is_empty() const { return _cur_seg == NULL; } 194 bool is_empty() const { return _cur_seg == NULL; }
194 195
195 E next() { return *next_addr(); } 196 E next() { return *next_addr(); }
196 E* next_addr(); 197 E* next_addr();
197 198
198 void sync(); // Sync the iterator's state to the stack's current state. 199 void sync(); // Sync the iterator's state to the stack's current state.
199 200
200 private: 201 private:
201 Stack<E>& _stack; 202 Stack<E, F>& _stack;
202 size_t _cur_seg_size; 203 size_t _cur_seg_size;
203 E* _cur_seg; 204 E* _cur_seg;
204 size_t _full_seg_size; 205 size_t _full_seg_size;
205 }; 206 };
206 207

mercurial