Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

map bug fix

  • Loading branch information...
commit 6e8f41640525c0020ecdeb461ab310ea44cf8c3f 1 parent 794857e
@cloudwu authored
Showing with 145 additions and 9 deletions.
  1. +3 −0  Makefile
  2. +22 −9 aoi.c
  3. +120 −0 testmap.c
View
3  Makefile
@@ -1,2 +1,5 @@
all:
gcc -o aoi -g -Wall aoi.c test.c
+
+test:
+ gcc -o testmap -g -Wall testmap.c
View
31 aoi.c
@@ -75,7 +75,11 @@ static struct object *
map_query(struct aoi_space *space, struct map * m, uint32_t id) {
uint32_t hash = id & (m->size-1);
struct map_slot *s = &m->slot[hash];
+ struct map_slot * empty = NULL;
for (;;) {
+ if (s->obj == NULL) {
+ empty = s;
+ }
if (s->id == id) {
if (s->obj == NULL) {
s->obj = new_object(space, id);
@@ -87,6 +91,11 @@ map_query(struct aoi_space *space, struct map * m, uint32_t id) {
}
s=&m->slot[s->next];
}
+ if (empty) {
+ empty->id = id;
+ empty->obj = new_object(space, id);
+ return empty->obj;
+ }
int i;
for (i=0;i<m->size;i++) {
if (m->slot[i].obj == NULL) {
@@ -120,8 +129,9 @@ map_query(struct aoi_space *space, struct map * m, uint32_t id) {
if (new_slot[j].obj == NULL) {
new_slot[j].id = m->slot[i].id;
new_slot[j].obj = m->slot[i].obj;
- new_slot[j].next = m->slot[i].next;
- m->slot[i].next = j;
+ new_slot[j].next = s->next;
+ s->next = j;
+ break;
}
}
}
@@ -144,22 +154,25 @@ map_foreach(struct map * m , void (*func)(void *ud, struct object *obj), void *u
}
}
-static void
-map_delete(struct map *m, uint32_t id) {
+static struct object *
+map_drop(struct map *m, uint32_t id) {
uint32_t hash = id & (m->size-1);
struct map_slot *s = &m->slot[hash];
for (;;) {
if (s->id == id) {
+ struct object * obj = s->obj;
s->obj = NULL;
- return;
+ return obj;
+ }
+ if (s->next < 0) {
+ return NULL;
}
- assert(s->next >= 0);
s=&m->slot[s->next];
}
}
static void
-delete_map(struct aoi_space *space, struct map * m) {
+map_delete(struct aoi_space *space, struct map * m) {
space->alloc(space->alloc_ud, m->slot, m->size * sizeof(struct map_slot));
space->alloc(space->alloc_ud, m , sizeof(*m));
}
@@ -194,7 +207,7 @@ inline static void
drop_object(struct aoi_space * space, struct object *obj) {
--obj->ref;
if (obj->ref <=0) {
- map_delete(space->object, obj->id);
+ map_drop(space->object, obj->id);
delete_object(space, obj);
}
}
@@ -243,7 +256,7 @@ delete_set(struct aoi_space *space, struct object_set * set) {
void
aoi_release(struct aoi_space *space) {
map_foreach(space->object, delete_object, space);
- delete_map(space, space->object);
+ map_delete(space, space->object);
delete_pair_list(space);
delete_set(space,space->watcher_static);
delete_set(space,space->marker_static);
View
120 testmap.c
@@ -0,0 +1,120 @@
+#include "aoi.c"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define MAX 1000
+
+static struct aoi_space * SPACE = NULL;
+static int INDEX[MAX];
+
+static void
+shuffle(int number) {
+ int i;
+ for (i=0;i<number * 2;i++) {
+ int idx1 = rand() % number;
+ int idx2 = rand() % number;
+ int temp = INDEX[idx1];
+ INDEX[idx1] = INDEX[idx2];
+ INDEX[idx2] = temp;
+ }
+}
+
+static void
+init(int number, int start) {
+ int i;
+ for (i=0;i<number;i++) {
+ INDEX[i] = i+start;
+ }
+}
+
+static void
+mnew(struct map *m, uint32_t id) {
+ struct object * obj = map_query(SPACE , m , id);
+// printf("new %u\n",id);
+ assert(obj->id == id);
+ assert(obj->ref == 1);
+}
+
+static void
+mdelete(struct map *m, uint32_t id) {
+ struct object * obj = map_drop(m , id);
+// printf("delete %u\n",id);
+ assert(obj != NULL);
+ assert(obj->id == id);
+ assert(obj->ref == 1);
+ drop_object(SPACE, obj);
+}
+
+static void
+test(struct map *m , int n, int start) {
+ init(n,start);
+ shuffle(n);
+ int i;
+ for (i=0;i<n;i++) {
+ mnew(m,INDEX[i]);
+ }
+ shuffle(n);
+ n = rand() % (n/2);
+ for (i=0;i<n;i++) {
+ mdelete(m,INDEX[i]);
+ }
+}
+
+static void
+check(void *ud, struct object * obj) {
+ struct map * m = ud;
+ printf("%u ",obj->id);
+ mdelete(m, obj->id);
+}
+
+struct alloc_cookie {
+ int count;
+ int max;
+ int current;
+};
+
+static void *
+my_alloc(void * ud, void *ptr, size_t sz) {
+ struct alloc_cookie * cookie = ud;
+ if (ptr == NULL) {
+ void *p = malloc(sz);
+ ++ cookie->count;
+ cookie->current += sz;
+ if (cookie->max < cookie->current) {
+ cookie->max = cookie->current;
+ }
+// printf("%p + %u\n",p, sz);
+ return p;
+ }
+ -- cookie->count;
+ cookie->current -= sz;
+// printf("%p - %u \n",ptr, sz);
+ free(ptr);
+ return NULL;
+}
+
+int
+main()
+{
+ struct alloc_cookie cookie = { 0,0,0 };
+ SPACE = aoi_create(my_alloc , &cookie);
+
+ struct map * m = map_new(SPACE);
+
+ int i;
+ for (i=0;i<10;i++) {
+ test(m,10,i*10);
+ }
+ test(m,100,100);
+ test(m,200,200);
+ test(m,500,500);
+
+ map_foreach(m,check,m);
+
+ map_delete(SPACE, m);
+ aoi_release(SPACE);
+
+ printf("max memory = %d, current memory = %d\n", cookie.max , cookie.current);
+ return 0;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.