Skip to content

Commit

Permalink
Bugfix
Browse files Browse the repository at this point in the history
 - FPQ_ITEMS() raised divide-by-zero before size was set
    (get rid of modulus operations)
Changed Integer coercion to return .elements()
Added .capacity() to return (apparent) allocated size
More tests, with better descriptions
More unification of the 3 different source files
  • Loading branch information
kurahaupo committed Mar 2, 2010
1 parent 163662d commit f1b7711
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 98 deletions.
71 changes: 50 additions & 21 deletions src/pmc/fixedpmcqueue.pmc
Expand Up @@ -75,7 +75,8 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue {
VTABLE void visit(PMC *info) {
FPQ_DECL_ATTRS(SELF);
PMC ** const storage = self.storage;
FPQ_ITERATE(i, VISIT_PMC(INTERP, info, storage[i]));
if (storage)
FPQ_ITERATE(i, VISIT_PMC(INTERP, info, storage[i]));
}

/* Size the queue. Cannot shrink the queue smaller than the number of items
Expand All @@ -85,53 +86,56 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue {
const INTVAL start = self.queue_start;
const INTVAL end = self.queue_end;
const INTVAL size = self.size;
if (newsize < FPQ_ITEMS())
const INTVAL items = FPQ_ITEMS();

if (newsize < items)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue: Cannot shrink size with items in queue");
if (newsize != size)
if (newsize != size) {
if (start == 0) {
FPQ_REALLOCATE(self.storage, newsize);
self.size = newsize;
} else {
INTVAL ptr = start;
PMC ** const oldstorage = self.storage;
PMC ** newstorage = FPQ_ALLOCATE(newsize);
INTVAL i = 0;
while (ptr != end) {
newstorage[i] = oldstorage[ptr];
FPQ_IDX_INCR(ptr);
i++;
if ( start > end ) {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*));
mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*));
} else {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*));
}
if (oldstorage)
mem_sys_free(oldstorage);
self.storage = newstorage;
self.size = newsize;
self.queue_start = 0;
self.queue_end = i;
self.queue_end = items;
}
}
}

/* Push an item onto the queue */
VTABLE void push_pmc(PMC *item) {
FPQ_DECL_ATTRS(SELF);
if (self.size == self.items)

if (FPQ_FULL())
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue: Pushed too many items");
self.storage[self.queue_end] = item;
FPQ_IDX_INCR(self.queue_end);
self.items++;
FPQ_IDXF_INCR(queue_end);
FPQ_ITEMS()++;
}

/* Pull an item off the queue */
VTABLE PMC* shift_pmc() {
FPQ_DECL_ATTRS(SELF);
PMC * first_item;
if(!self.items)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue: No items to shift");

if (FPQ_EMPTY())
return PMCNULL;
first_item = self.storage[self.queue_start];
FPQ_IDX_INCR(self.queue_start);
self.items--;
FPQ_ITEMS()--;
FPQ_IDXF_INCR(queue_start);
return first_item;
}

Expand All @@ -146,18 +150,36 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue {
FPQ_DECL_ATTRS(SELF);
return FPQ_ITEMS();
}
VTABLE INTVAL get_integer() {
FPQ_DECL_ATTRS(SELF);
return FPQ_ITEMS();
}

VTABLE INTVAL isnull() {
FPQ_DECL_ATTRS(SELF);
return self.size <= 0;
}

/* Total amount of allocated storage slots in the queue */
VTABLE INTVAL get_integer() {
METHOD capacity() {
FPQ_DECL_ATTRS(SELF);
return(self.size);
PMC * result;
if (self.size <= 0)
result = PMCNULL;
else {
result = Parrot_pmc_new(INTERP,
Parrot_get_ctx_HLL_type(INTERP,
enum_class_Integer));
VTABLE_set_integer_native(INTERP, result, self.size);
}
RETURN(PMC* result);
}

/* Convert the queue to a FixedPMCArray. The array will have the same
length as the queue, all additional spaces will contain PMCNULL */
METHOD to_array() {
PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray);
FPQ_DECL_ATTRS(SELF);
PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray);
const INTVAL size = self.size;
PMC ** const s = self.storage;
INTVAL i = 0;
Expand Down Expand Up @@ -196,3 +218,10 @@ pmclass FixedPMCQueue dynpmc auto_attrs provides queue {
FPQ_ITEMS() = 0;
}
}

/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/
75 changes: 52 additions & 23 deletions src/pmc/fixedpmcqueue2.pmc
Expand Up @@ -5,10 +5,11 @@
#define FPQ_IDX_DIFF(x, y) (((x) + self.size - (y)) % self.size)
#define FPQ_IDX_INCR(x) (x) = FPQ_IDX_ADD((x), 1)
#define FPQ_IDXF_INCR(f) FPQ_IDX_INCR(self.f)
#define FPQ_ITEMS() FPQ_IDX_DIFF(self.queue_end, self.queue_start)
#define FPQ_ITEMS() (self.size > 0 ? FPQ_IDX_DIFF(self.queue_end, self.queue_start) : 0)
#define FPQ_EMPTY() (self.queue_start == self.queue_end)
#define FPQ_FULL() ((self.queue_end + 1) % self.size == self.queue_start)
#define FPQ_FULL() (self.queue_end + 1 - self.queue_start == 0 || self.queue_end + 1 - self.queue_start == self.size)
// (self.queue_start == self.queue_end+1 || self.queue_start == 0 && self.queue_end == self.size-1)
// ((self.queue_end + 1) % self.size == self.queue_start)
#define FPQ_ALLOCATE(len) mem_allocate_n_typed(len, PMC *)
#define FPQ_REALLOCATE(p, len) mem_realloc_n_typed(p, len, PMC *)
#define FPQ_ITERATE(index,func) { \
Expand Down Expand Up @@ -83,33 +84,40 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue {
const INTVAL start = self.queue_start;
const INTVAL end = self.queue_end;
const INTVAL size = self.size;
INTVAL items = FPQ_ITEMS();
const INTVAL items = FPQ_ITEMS();

if (newsize < items)
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue2: Cannot shrink size with items in queue");

++newsize; /* reserve one more slot than actually used, so that 0 <= items < size */
if (newsize != size) {
PMC ** const oldstorage = self.storage;
PMC ** newstorage = FPQ_ALLOCATE(newsize);
if ( start > end ) {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*));
mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*));
} else if ( start < end ) {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*));
if (start == 0) {
FPQ_REALLOCATE(self.storage, newsize);
self.size = newsize;
} else {
PMC ** const oldstorage = self.storage;
PMC ** newstorage = FPQ_ALLOCATE(newsize);
if ( start > end ) {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (size - start) * sizeof(PMC*));
mem_sys_memmove( &newstorage[size - start], &oldstorage[0], end * sizeof(PMC*));
} else {
mem_sys_memmove( &newstorage[0], &oldstorage[start], (end - start) * sizeof(PMC*));
}
if (oldstorage)
mem_sys_free(oldstorage);
self.storage = newstorage;
self.size = newsize;
self.queue_start = 0;
self.queue_end = items;
}
if (oldstorage)
mem_sys_free(oldstorage);
self.storage = newstorage;
self.size = newsize;
self.queue_start = 0;
self.queue_end = items;
}
}

/* Push an item onto the queue */
VTABLE void push_pmc(PMC *item) {
FPQ_DECL_ATTRS(SELF);

if (FPQ_FULL())
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue2: Pushed too many items");
Expand All @@ -121,9 +129,9 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue {
VTABLE PMC* shift_pmc() {
FPQ_DECL_ATTRS(SELF);
PMC * first_item;
if(FPQ_EMPTY())
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
"FixedPMCQueue2: No items to shift");

if (FPQ_EMPTY())
return PMCNULL;
first_item = self.storage[self.queue_start];
FPQ_IDXF_INCR(queue_start);
return first_item;
Expand All @@ -140,24 +148,38 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue {
FPQ_DECL_ATTRS(SELF);
return FPQ_ITEMS();
}
VTABLE INTVAL get_integer() {
FPQ_DECL_ATTRS(SELF);
return FPQ_ITEMS();
}

/* Total amount of allocated storage slots in the queue */
VTABLE INTVAL get_integer() {
METHOD capacity() {
FPQ_DECL_ATTRS(SELF);
return(self.size);
PMC * result;
if (self.size <= 0)
result = PMCNULL;
else {
result = Parrot_pmc_new(INTERP,
Parrot_get_ctx_HLL_type(INTERP,
enum_class_Integer));
VTABLE_set_integer_native(INTERP, result, self.size-1); // available size is one less than allocate space
}
RETURN(PMC* result);
}

/* Convert the queue to a FixedPMCArray. The array will have the same
length as the queue, all additional spaces will contain PMCNULL */
METHOD to_array() {
FPQ_DECL_ATTRS(SELF);
PMC * newarray = Parrot_pmc_new(INTERP, enum_class_FixedPMCArray);
const INTVAL size = self.size;
PMC ** const s = self.storage;
INTVAL i = 0;

VTABLE_set_integer_native(INTERP, newarray, self.size);
VTABLE_set_integer_native(INTERP, newarray, size);
FPQ_ITERATE(ptr, VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, s[ptr]));
while (i < self.size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL);
while (i < size) VTABLE_set_pmc_keyed_int(INTERP, newarray, i++, PMCNULL);
RETURN(PMC* newarray);
}

Expand Down Expand Up @@ -188,3 +210,10 @@ pmclass FixedPMCQueue2 dynpmc auto_attrs provides queue {
self.queue_end = 0;
}
}

/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4:
*/

0 comments on commit f1b7711

Please sign in to comment.