Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
146 lines (130 sloc) 3.9 KB
#include "parrot/parrot.h"
#define RPQ_ATTRS_CONST(x) Parrot_ResizablePMCQueue_attributes * const (x)
#define RPQ_GET_ATTRS(x) PARROT_RESIZABLEPMCQUEUE(x)
#define RPQ_GET_ROOT(a) ((rpq_node *)(a)->root)
#define RPQ_GET_TOP(a) ((rpq_node *)(a)->top)
typedef struct _rpq_node {
struct _rpq_node * next;
PMC *item;
} rpq_node;
static
rpq_node *
rpq_alloc_new_node(PMC *item)
{
rpq_node * const newnode = (rpq_node *)mem_sys_allocate(sizeof(rpq_node));
newnode->next = NULL;
newnode->item = item;
return newnode;
}
static
PMC *
rpq_free_node(rpq_node *node)
{
PMC * const item = node->item;
mem_sys_free(node);
return item;
}
static
PMC *
rpq_read_node(rpq_node *node)
{
PMC * const item = node->item;
return item;
}
pmclass ResizablePMCQueue dynpmc auto_attrs provides queue {
ATTR void *root;
ATTR void *top;
VTABLE void init() {
PObj_custom_mark_destroy_SETALL(SELF);
}
VTABLE void destroy() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
while (root) {
rpq_node * const next = root->next;
mem_sys_free(root);
root = next;
}
}
VTABLE void mark() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
while (root) {
PMC * const item = rpq_read_node(root);
Parrot_gc_mark_PMC_alive(INTERP, item);
root = root->next;
}
}
VTABLE void push_pmc(PMC *value) {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * const node = rpq_alloc_new_node(value);
rpq_node * const top = RPQ_GET_TOP(attrs);
rpq_node * const root = RPQ_GET_ROOT(attrs);
/* If we don't have a top, it's because the queue is empty. */
if (!root) {
attrs->root = node;
attrs->top = node;
} else {
top->next = node;
attrs->top = node;
}
}
VTABLE PMC *shift_pmc() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * const root = RPQ_GET_ROOT(attrs);
if (!root)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"ResizablePMCQueue: Shift from empty queue");
attrs->root = root->next;
return rpq_free_node(root);
}
/* Get the number of items in the queue. WARNING: O(n) */
VTABLE INTVAL elements() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
INTVAL count = 0;
while (root) {
count++;
root = root->next;
}
return count;
}
VTABLE INTVAL get_bool() {
const INTVAL elems = VTABLE_elements(INTERP, SELF);
const INTVAL has_elems = (elems > 0);
return has_elems;
}
METHOD to_array() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
PMC * newarray = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray);
INTVAL idx = 0;
while (root) {
VTABLE_set_pmc_keyed_int(INTERP, newarray, idx, root->item);
idx++;
root = root->next;
}
RETURN(PMC *newarray);
}
METHOD total_mem_size() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
INTVAL size = sizeof(PMC) + sizeof(Parrot_ResizablePMCQueue_attributes);
while (root) {
size += sizeof(rpq_node);
root = root->next;
}
RETURN(INTVAL size);
}
METHOD clear() {
RPQ_ATTRS_CONST(attrs) = RPQ_GET_ATTRS(SELF);
rpq_node * root = RPQ_GET_ROOT(attrs);
while (root) {
rpq_node * const next = root->next;
mem_sys_free(root);
root = next;
}
attrs->root = NULL;
attrs->top = NULL;
}
}