/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_UTILITIES_STACK_HPP
#define SHARE_VM_UTILITIES_STACK_HPP
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
// Class Stack (below) grows and shrinks by linking together "segments" which
// are allocated on demand. Segments are arrays of the element type (E) plus an
// extra pointer-sized field to store the segment link. Recently emptied
// segments are kept in a cache and reused.
//
//
// The size of an element must either evenly divide the size of a pointer or be
// a multiple of the size of a pointer.
//
// Destructors are not called for elements popped off the stack, so element
// types which rely on destructors for things like reference counting will not
// work properly.
//
// Class Stack allocates segments from the C heap. However, two protected
//
// virtual void* alloc(size_t bytes);
// virtual void free(void* addr, size_t bytes);
//
// The alloc() method must return storage aligned for any use. The
// implementation in class Stack assumes that alloc() will terminate the process
// if the allocation fails.
template <class E, MEMFLAGS F> class StackIterator;
// factored out to reduce template code duplication.
{
public:
// allowed in cache.
protected:
// The ctor arguments correspond to the like-named functions above.
// segment_size: number of items per segment
// max_cache_size: maxmium number of *segments* to cache
// max_size: maximum number of items allowed, rounded to a multiple of
// the segment size (0 == unlimited)
// Round max_size to a multiple of the segment size. Treat 0 as unlimited.
protected:
};
#ifdef __GNUC__
#define inline
#endif // __GNUC__
template <class E, MEMFLAGS F>
{
public:
friend class StackIterator<E, F>;
// segment_size: number of items per segment
// max_cache_size: maxmium number of *segments* to cache
// max_size: maximum number of items allowed, rounded to a multiple of
// the segment size (0 == unlimited)
// Performance sensitive code should use is_empty() instead of size() == 0 and
// is_full() instead of size() == max_size(). Using a conditional here allows
}
inline E pop();
// Clear everything from the stack, releasing the associated memory. If
// clear_cache is true, also release any cached segments.
void clear(bool clear_cache = false);
static inline size_t default_segment_size();
protected:
// Each segment includes space for _seg_size elements followed by a link
// (pointer) to the previous segment; the space is allocated as a single block
// of size segment_bytes(). _seg_size is rounded up if necessary so the link
// is properly aligned. The C struct for the layout would be:
//
// struct segment {
// E elements[_seg_size];
// E* link;
// };
// Round up seg_size to keep the link field aligned.
void push_segment();
void pop_segment();
private:
};
{
public:
// If this class becomes widely used, it may make sense to save the Thread
// and use it when allocating segments.
// ResourceStack(size_t segment_size = Stack<E, F>::default_segment_size()):
{ }
// Set the segment pointers to NULL so the parent dtor does not free them;
// that must be done by the ResourceMark code.
protected:
private:
void clear(bool clear_cache = false);
};
template <class E, MEMFLAGS F>
{
public:
E* next_addr();
void sync(); // Sync the iterator's state to the stack's current state.
private:
E* _cur_seg;
};
#ifdef __GNUC__
#undef inline
#endif // __GNUC__
#endif // SHARE_VM_UTILITIES_STACK_HPP