Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

134 lines (119 sloc) 4.523 kb
#include "parrot/parrot.h"
#define RPS_POINTERS_PER_CHUNK 16
#define RPS_ATTRS_CONST(x) Parrot_ResizablePMCStack2_attributes * const (x)
#define RPS_GET_ATTRS(x) PARROT_RESIZABLEPMCSTACK2(x)
#define RPS_INITIAL_BUFFER_SIZE 16
#define RPS_GROW_FACTOR 2
#define RPS_NEXT_SIZE_GROW(s) ((s) * RPS_GROW_FACTOR)
#define RPS_NEXT_SIZE_SHRINK(s) ((s) / RPS_GROW_FACTOR)
#define RPS_ALLOCATE(s) (PMC **)mem_sys_allocate(s * sizeof(PMC *))
#define RPS_REALLOCATE(s, x) (PMC **)mem_sys_realloc((s), (x) * sizeof(PMC*))
#define RPS_GET_STORAGE(a) ((a)->storage)
/* ResizablePMCStack2 is a dynamically-growing First-In-Last-Out stack structure.
It is optimized for high-throughput push/pop access. It uses a geometrically
growing flat memory buffer to hold data. */
pmclass ResizablePMCStack2 dynpmc auto_attrs provides stack {
ATTR PMC **storage;
ATTR INTVAL items;
ATTR INTVAL size;
/* Initialize the PMC and allocate the first chunk */
VTABLE void init() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
attrs->storage = RPS_ALLOCATE(RPS_INITIAL_BUFFER_SIZE);
attrs->size = RPS_INITIAL_BUFFER_SIZE;
/* ->items already zeroed */
}
/* Destroy the PMC and free all allocated storage */
VTABLE void destroy() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
PMC ** const s = attrs->storage;
if (s)
mem_sys_free(s);
}
/* Mark the stack for GC */
VTABLE void mark() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
PMC ** const s = RPS_GET_STORAGE(attrs);
if (s) {
INTVAL i = 0;
const INTVAL items = attrs->items;
for (i = 0; i < items; i++)
Parrot_gc_mark_PMC_alive(INTERP, s[i]);
}
}
VTABLE void freeze(PMC *info) {
}
VTABLE void thaw(PMC *info) {
}
VTABLE void visit(PMC *info) {
}
/* Push a PMC onto the stack */
VTABLE void push_pmc(PMC *item) {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
const INTVAL items = attrs->items;
const INTVAL size = attrs->size;
PMC ** s = attrs->storage;
if (items == size) {
const INTVAL newsize = RPS_NEXT_SIZE_GROW(size);
s = RPS_REALLOCATE(s, newsize);
attrs->storage = s;
attrs->size = newsize;
}
s[items] = item;
attrs->items = items + 1;
}
/* Pop a PMC off the stack */
VTABLE PMC* pop_pmc() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
const INTVAL items = attrs->items - 1;
//const INTVAL size = attrs->size;
PMC ** const s = attrs->storage;
PMC * item;
if (items == -1)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"ResizablePMCStack2: Pop from empty stack");
item = s[items];
attrs->items = items;
return item;
}
/* Get the total number of elements. WARNING: O(N) */
VTABLE INTVAL elements() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
const INTVAL items = attrs->items;
return items;
}
VTABLE INTVAL get_bool() {
const INTVAL elems = VTABLE_elements(INTERP, SELF);
const INTVAL has_elems = (elems > 0);
return has_elems;
}
/* Get a ResizablePMCArray containing the contents of the stack */
METHOD to_array() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
const INTVAL items = attrs->items;
PMC ** const s = attrs->storage;
PMC * const newarray = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
INTVAL i = 0;
for (i = 0; i < items; i++)
VTABLE_set_pmc_keyed_int(INTERP, newarray, i, s[i]);
RETURN(PMC *newarray);
}
/* Get the total allocated memory size, in bytes. Includes the size of the
PMC structure and attribute structure */
METHOD total_mem_size() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
const INTVAL size = attrs->size;
INTVAL total = sizeof(PMC) + sizeof(Parrot_ResizablePMCStack2_attributes);
total += size * sizeof(PMC *);
RETURN(INTVAL total);
}
METHOD clear() {
RPS_ATTRS_CONST(attrs) = RPS_GET_ATTRS(SELF);
PMC ** const s = attrs->storage;
if (s)
mem_sys_free(s);
attrs->storage = RPS_ALLOCATE(RPS_INITIAL_BUFFER_SIZE);
attrs->size = RPS_INITIAL_BUFFER_SIZE;
attrs->items = 0;
}
}
Jump to Line
Something went wrong with that request. Please try again.