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:
parent
98d6ba3967
commit
ff51ea54e6
2 changed files with 17 additions and 6 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue