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,
|
priqueue_init (PriQueue self,
|
||||||
size_t element_size,
|
size_t element_size,
|
||||||
priqueue_cmp_fn cmpfn,
|
priqueue_cmp_fn cmpfn,
|
||||||
|
priqueue_copy_fn copyfn,
|
||||||
priqueue_resize_fn resizefn)
|
priqueue_resize_fn resizefn)
|
||||||
{
|
{
|
||||||
NOBUG_INIT_FLAG (priqueue);
|
NOBUG_INIT_FLAG (priqueue);
|
||||||
|
|
@ -48,6 +49,10 @@ priqueue_init (PriQueue self,
|
||||||
self->used = self->high_water = self->low_water = 0;
|
self->used = self->high_water = self->low_water = 0;
|
||||||
self->cmpfn = cmpfn;
|
self->cmpfn = cmpfn;
|
||||||
|
|
||||||
|
if (!copyfn)
|
||||||
|
copyfn = memcpy;
|
||||||
|
self->copyfn = copyfn;
|
||||||
|
|
||||||
if (!resizefn)
|
if (!resizefn)
|
||||||
resizefn = priqueue_clib_resize;
|
resizefn = priqueue_clib_resize;
|
||||||
self->resizefn = resizefn;
|
self->resizefn = resizefn;
|
||||||
|
|
@ -177,11 +182,11 @@ pq_up (PriQueue self, void* tmp)
|
||||||
|
|
||||||
while (p && self->cmpfn (tmp, pq_index(self, p-1)) < 0)
|
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;
|
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)
|
if (self->cmpfn (tmp, pq_index(self, n-1)) < 0)
|
||||||
break;
|
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;
|
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>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
@ -303,10 +308,11 @@ int main()
|
||||||
r = priqueue_init (&pq,
|
r = priqueue_init (&pq,
|
||||||
sizeof (int),
|
sizeof (int),
|
||||||
cmpintptr,
|
cmpintptr,
|
||||||
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
ENSURE (r==&pq);
|
ENSURE (r==&pq);
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
data = 10;
|
data = 10;
|
||||||
r = priqueue_insert (&pq, &data);
|
r = priqueue_insert (&pq, &data);
|
||||||
ENSURE (r==&pq);
|
ENSURE (r==&pq);
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ typedef priqueue* PriQueue;
|
||||||
/* function to compare 2 keys, mandatory */
|
/* function to compare 2 keys, mandatory */
|
||||||
typedef int (*priqueue_cmp_fn)(void*, void*);
|
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)
|
/* 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),
|
or at priqueue_destroy (with queue != NULL, used elements == 0),
|
||||||
optional.
|
optional.
|
||||||
|
|
@ -64,6 +67,7 @@ struct priqueue_struct
|
||||||
unsigned low_water; // size for shrinking the queue
|
unsigned low_water; // size for shrinking the queue
|
||||||
|
|
||||||
priqueue_cmp_fn cmpfn;
|
priqueue_cmp_fn cmpfn;
|
||||||
|
priqueue_copy_fn copyfn;
|
||||||
|
|
||||||
priqueue_resize_fn resizefn;
|
priqueue_resize_fn resizefn;
|
||||||
};
|
};
|
||||||
|
|
@ -77,6 +81,7 @@ PriQueue
|
||||||
priqueue_init (PriQueue self,
|
priqueue_init (PriQueue self,
|
||||||
size_t element_size,
|
size_t element_size,
|
||||||
priqueue_cmp_fn cmpfn,
|
priqueue_cmp_fn cmpfn,
|
||||||
|
priqueue_copy_fn copyfn,
|
||||||
priqueue_resize_fn resizefn);
|
priqueue_resize_fn resizefn);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue