Skip to content

Commit

Permalink
Fixes to radixmap.
Browse files Browse the repository at this point in the history
  • Loading branch information
zedshaw committed Apr 14, 2012
1 parent 42dd4f3 commit 3db495c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 172 deletions.
118 changes: 32 additions & 86 deletions src/lcthw/radixmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,38 @@
#include <lcthw/radixmap.h>
#include <lcthw/dbg.h>

RadixMap *RadixMap_create(size_t max)
{
RadixMap *map = calloc(sizeof(RadixMap), 1);
check_mem(map);

map->contents = calloc(sizeof(RMElement), max + 1);
check_mem(map->contents);

map->temp = calloc(sizeof(RMElement), max + 1);
check_mem(map->temp);

map->max = max;
map->end = 0;

return map;
error:
return NULL;
}

void RadixMap_destroy(RadixMap *map)
{
if(map) {
free(map->contents);
free(map->temp);
free(map);
}
}


#define ByteOf(x,y) (((uint8_t *)x)[(y)])

static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64_t *dest)
static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest)
{
uint64_t count[256] = {0};
uint64_t *cp = NULL;
Expand All @@ -20,7 +49,7 @@ static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64
uint64_t c = 0;

// count occurences of every byte value
for (sp = source, end = source + N; sp < end; sp++) {
for (sp = source, end = source + max; sp < end; sp++) {
count[ByteOf(sp, offset)]++;
}

Expand All @@ -32,7 +61,7 @@ static inline void radix_sort(short offset, uint64_t N, uint64_t *source, uint64
}

// fill dest with the right values in the right place
for (sp = source, end = source + N; sp < end; sp++) {
for (sp = source, end = source + max; sp < end; sp++) {
cp = count + ByteOf(sp, offset);
dest[*cp] = *sp;
++(*cp);
Expand All @@ -50,35 +79,6 @@ void RadixMap_sort(RadixMap *map)
radix_sort(3, map->end, temp, source);
}

/**
* This is primarily used by the tail sorted version to find the
* lowest place to start sorting. It's a quick binary search
* of the data elements and returns whatever lowest value was
* hit.
*/
RMElement *RadixMap_find_lowest(RadixMap *map, uint32_t to_find)
{
int low = 0;
int high = map->end - 1;
RMElement *data = map->contents;

while (low <= high) {
int middle = low + (high - low)/2;
uint32_t key = data[middle].data.key;

if (to_find < key) {
high = middle - 1;
} else if (to_find > key) {
low = middle + 1;
} else {
return &data[middle];
}
}

return &data[low];
}


RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
{
int low = 0;
Expand All @@ -101,36 +101,6 @@ RMElement *RadixMap_find(RadixMap *map, uint32_t to_find)
return NULL;
}


RadixMap *RadixMap_create(size_t max)
{
RadixMap *map = calloc(sizeof(RadixMap), 1);
check_mem(map);

map->contents = calloc(sizeof(RMElement), max + 1);
check_mem(map->contents);

map->temp = calloc(sizeof(RMElement), max + 1);
check_mem(map->temp);

map->max = max;
map->end = 0;

return map;
error:
return NULL;
}

void RadixMap_destroy(RadixMap *map)
{
if(map) {
free(map->contents);
free(map->temp);
free(map);
}
}


int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value)
{
check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX.");
Expand Down Expand Up @@ -168,27 +138,3 @@ int RadixMap_delete(RadixMap *map, RMElement *el)
}


uint32_t RadixMap_push(RadixMap *map, uint32_t value)
{
check(map->end + 1 < map->max, "RadixMap is full.");
map->counter++;

if(map->counter == UINT32_MAX) {
// wrap it around so that we skip the ending trigger
map->counter = 0;
}

if(map->end == 0 || map->contents[map->end-1].data.key < map->counter) {
// this one already fits on the end so we're done
RMElement element = {.data = {.key = map->counter, .value = value}};
map->contents[map->end++] = element;
} else {
// looks like we probably wrapped around and need to do the slower add
check(RadixMap_add(map, map->counter, value) == 0, "Failed to add on push.");
}

return map->counter;

error:
return UINT32_MAX;
}
86 changes: 0 additions & 86 deletions tests/radixmap_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,6 @@ static int make_random(RadixMap *map)
return 0;
}

static int push_random_values(RadixMap *map)
{
size_t i = 0;
for(i = 0; i < map->max - 1; i++) {
uint32_t value = (uint32_t)(rand () | (rand () << 16));
uint32_t key = RadixMap_push(map, value);
check(key != UINT32_MAX, "Got an invalid return.");
}
return 1;
error:
return 0;
}

static int check_order(RadixMap *map)
{
RMElement d1, d2;
Expand Down Expand Up @@ -84,18 +71,6 @@ static char *test_operations()
mu_assert(test_search(map), "Failed the search test.");
mu_assert(check_order(map), "RadixMap didn't stay sorted after search.");

RadixMap_destroy(map);

map = RadixMap_create(N);
mu_assert(map != NULL, "Failed to make the map.");

debug("PUSHING VALUES");
mu_assert(push_random_values(map), "Didn't push random values.");
debug("VALUES PUSHED!");

mu_assert(check_order(map), "Map wasn't sorted after pushes.");

debug("DOING DELETES");
while(map->end > 0) {
RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key);
mu_assert(el != NULL, "Should get a result.");
Expand All @@ -115,73 +90,12 @@ static char *test_operations()
}


static char *test_simulate()
{
uint32_t fd = (uint32_t)(rand() | (rand() << 16));
int i = 0;
size_t key = 0;
int connects = 0, disconnects = 0, activities = 0;
RMElement *el = NULL;
RadixMap *map = RadixMap_create(500);
// start the counter at just near max to test that out
map->counter = UINT32_MAX - 100;

debug("COUNTER: %u", map->counter);

for(i = 0; i < 10; i++) {
// seed it up
RadixMap_push(map, fd++);
}

debug("ENTERING LOOP");
for(i = 0; i < 10000; i++) {
switch((rand() + 1) % 4) {
case 0:
// connect, so add it on
RadixMap_push(map, fd++);
connects++;
break;
case 1:
// disconnect, so remove
if(map->end > 0) {
key = (rand() + 1) % map->end;
el = &map->contents[key];
el = RadixMap_find(map, el->data.key);
mu_assert(el != NULL, "Failed to find the key.");
RadixMap_delete(map, el);
}
disconnects++;
break;

default:
// activity so find for doing stuff
if(map->end > 0) {
key = (rand() + 1) % map->end;
el = &map->contents[key];
el = RadixMap_find(map, el->data.key);
mu_assert(el != NULL, "Failed to find the key.");
}
activities++;
break;
}

if(map->end == 0) {
// make a new connect if we're empty
RadixMap_push(map, fd++);
}
}

RadixMap_destroy(map);
return NULL;
}

char *all_tests()
{
mu_suite_start();
srand(time(NULL));

mu_run_test(test_operations);
mu_run_test(test_simulate);

return NULL;
}
Expand Down

0 comments on commit 3db495c

Please sign in to comment.