Add a copy function to the priqueue

by providing a custom copy function one can adjust otherwise non-copyable
elements. This should be used cautionary because dereferencing elements may
poison the cache and thus have some considerable performance impact
(profile this)
This commit is contained in:
Christian Thaeter 2011-06-21 23:35:50 +02:00 committed by Ichthyostega
parent 98d6ba3967
commit ff51ea54e6
2 changed files with 17 additions and 6 deletions

View file

@ -33,6 +33,7 @@ PriQueue
priqueue_init (PriQueue self,
size_t element_size,
priqueue_cmp_fn cmpfn,
priqueue_copy_fn copyfn,
priqueue_resize_fn resizefn)
{
NOBUG_INIT_FLAG (priqueue);
@ -48,6 +49,10 @@ priqueue_init (PriQueue self,
self->used = self->high_water = self->low_water = 0;
self->cmpfn = cmpfn;
if (!copyfn)
copyfn = memcpy;
self->copyfn = copyfn;
if (!resizefn)
resizefn = priqueue_clib_resize;
self->resizefn = resizefn;
@ -177,11 +182,11 @@ pq_up (PriQueue self, void* tmp)
while (p && self->cmpfn (tmp, pq_index(self, p-1)) < 0)
{
memcpy (pq_index (self, i-1), pq_index (self, p-1), self->element_size);
self->copyfn (pq_index (self, i-1), pq_index (self, p-1), self->element_size);
i=p; p=i/2;
}
memcpy (pq_index (self, i-1), tmp, self->element_size);
self->copyfn (pq_index (self, i-1), tmp, self->element_size);
}
@ -222,10 +227,10 @@ pq_down (PriQueue self, void* tmp)
if (self->cmpfn (tmp, pq_index(self, n-1)) < 0)
break;
memcpy (pq_index (self, i-1), pq_index (self, n-1), self->element_size);
self->copyfn (pq_index (self, i-1), pq_index (self, n-1), self->element_size);
i = n;
}
memcpy (pq_index (self, i-1), tmp, self->element_size);
self->copyfn (pq_index (self, i-1), tmp, self->element_size);
}
@ -257,7 +262,7 @@ priqueue_remove (PriQueue self)
#if 0 /* testing */
#ifdef PRIQUEUE_TEST /* testing */
#include <stdio.h>
@ -303,10 +308,11 @@ int main()
r = priqueue_init (&pq,
sizeof (int),
cmpintptr,
NULL,
NULL);
ENSURE (r==&pq);
#if 0
#if 1
data = 10;
r = priqueue_insert (&pq, &data);
ENSURE (r==&pq);

View file

@ -42,6 +42,9 @@ typedef priqueue* PriQueue;
/* function to compare 2 keys, mandatory */
typedef int (*priqueue_cmp_fn)(void*, void*);
/* function to copy elements, optional. Has the same prototype as memcpy which is used by default */
typedef void *(*priqueue_copy_fn)(void *dest, const void *src, size_t n);
/* called when used hits the high or low water marks and initially by priqueue_init() (with queue==NULL)
or at priqueue_destroy (with queue != NULL, used elements == 0),
optional.
@ -64,6 +67,7 @@ struct priqueue_struct
unsigned low_water; // size for shrinking the queue
priqueue_cmp_fn cmpfn;
priqueue_copy_fn copyfn;
priqueue_resize_fn resizefn;
};
@ -77,6 +81,7 @@ PriQueue
priqueue_init (PriQueue self,
size_t element_size,
priqueue_cmp_fn cmpfn,
priqueue_copy_fn copyfn,
priqueue_resize_fn resizefn);