commit fbeeb6961b924a2f705656ccea36f5eb737004fd
parent 75faf6813342d666d3eb289e16a421f34d44b025
Author: William Casarin <jb55@jb55.com>
Date: Sat, 29 Jun 2019 00:45:33 -0700
simple memmove resource managers for now
Diffstat:
3 files changed, 66 insertions(+), 106 deletions(-)
diff --git a/src/resource.c b/src/resource.c
@@ -10,7 +10,8 @@
static u64 resource_uuids = 0;
static inline void *index_resource(struct resource_manager *r, int i) {
- return &r->resources[i * r->elem_size];
+ unsigned char *p = r->resources;
+ return &p[i * r->elem_size];
}
void *get_all_resources(struct resource_manager *r, u32 *count, struct resource_id **ids) {
@@ -39,8 +40,8 @@ void init_resource_manager(struct resource_manager *r, u32 elem_size,
assert(initial_elements != 0);
- r->resources = calloc(initial_elements, elem_size);
- r->ids = calloc(initial_elements, sizeof(*r->ids));
+ r->resources = calloc(initial_elements+1, elem_size);
+ r->ids = calloc(initial_elements+1, sizeof(*r->ids));
}
void destroy_resource_manager(struct resource_manager *r) {
@@ -54,37 +55,30 @@ static int refresh_id(struct resource_manager *r, struct resource_id *id,
// rollover is ok
/* assert(->generation <= esys.generation); */
if (id->generation != r->generation) {
- debug("id gen %d != res gen %d, refreshing\n", id->generation, r->generation);
+ /* debug("id gen %d != res gen %d, refreshing\n", id->generation, r->generation); */
// try to find uuid in new memory layout
for (u32 i = 0; i < r->resource_count; i++) {
- struct resource_id *new_id = &r->ids[i];
- if (new_id->uuid == id->uuid) {
- new->index = new_id->index;
+ struct resource_id *newer_id = &r->ids[i];
+ if (newer_id->uuid == id->uuid) {
+ /* debug("found %llu, ind %d -> %d\n", new_id->uuid, new_id->index, new->index); */
+ new->index = newer_id->index;
new->generation = r->generation;
- return 1;
+ return REFRESHED_ID;
}
}
// entity was deleted
- return 0;
+ return RESOURCE_DELETED;
}
// doesn't need refreshed
- return 2;
+ return REFRESH_NOT_NEEDED;
}
-
+
int is_resource_destroyed(struct resource_id *id) {
return id->generation == 0;
}
-/* static struct resource_id new_id(struct resource_manager *r) { */
-/* return (struct resource_id){ */
-/* .index = r->resource_count, */
-/* .uuid = ++resource_uuids, */
-/* .generation = r->generation, */
-/* }; */
-/* } */
-
static void new_id(struct resource_manager *r, struct resource_id *id)
{
id->index = r->resource_count;
@@ -99,8 +93,10 @@ static void resize(struct resource_manager *r)
u32 new_size = r->resource_count * 1.5;
if (new_size >= r->max_capacity)
new_size = r->max_capacity;
+
debug("resizing new_size %d\n", new_size);
- new_mem = realloc(r->resources, new_size * r->elem_size);
+
+ new_mem = realloc(r->resources, (new_size+1) * r->elem_size);
if (!new_mem) {
// yikes, out of memory, bail
assert(new_mem);
@@ -108,7 +104,7 @@ static void resize(struct resource_manager *r)
}
r->resources = new_mem;
- new_mem = realloc(r->ids, sizeof(struct resource_id) * new_size);
+ new_mem = realloc(r->ids, sizeof(struct resource_id) * (new_size+1));
if (!new_mem) {
// yikes, out of memory, bail
@@ -122,70 +118,6 @@ static void resize(struct resource_manager *r)
r->generation += 2;
}
-static int compact(struct resource_manager *r)
-{
- int free_slot = -1;
- int fresh_elements = 0;
- u8 *dst;
- u8 *src = NULL;
- u8 * const start = r->resources;
-
- for (int i = 0; i < (int)r->resource_count; i++) {
- if (free_slot != -1 && r->ids[i].generation != 0) {
- debug("res: moving from %d to empty slot %d\n", i, free_slot);
- src = index_resource(r, i);
- dst = index_resource(r, free_slot);
-
- if (src == dst) {
- unusual("resource compact: trying to compact into the same location\n");
- continue;
- }
-
- debug("res: src %zu dst %zu count %d cap %d\n", src - start, dst - start,
- r->resource_count, r->current_capacity);
-
- // move data to free slot, clear the old slot
- assert(dst + r->elem_size <= start + r->elem_size * r->current_capacity);
- memcpy(dst, src, r->elem_size);
- assert(src + r->elem_size <= start + r->elem_size * r->current_capacity);
- memset(src, 0, r->elem_size);
-
- // move ids to free slot, increasing generation
- r->ids[free_slot] = r->ids[i];
- r->ids[free_slot].generation++;
- r->ids[free_slot].index = free_slot;
-
- // clear the old data
- memset(&r->ids[i], 0, sizeof(*r->ids));
- free_slot = min(free_slot, i);
- fresh_elements++;
- }
- else if (r->ids[i].generation == 0) {
- debug("res: found deleted slot %d\n", i);
- free_slot = free_slot == -1 ? i : min(free_slot, i);
- }
- else {
- fresh_elements++;
- }
-
- }
-
- if ((int)r->resource_count != fresh_elements)
- debug("res: updated resource_count to %d\n", fresh_elements);
- r->resource_count = fresh_elements;
-
- return fresh_elements;
-}
-
-static void compact_or_resize(struct resource_manager *r)
-{
- int orig = r->resource_count;
- int compacted = compact(r);
- debug("%d compacted to %d > %d?\n", orig, compacted, r->current_capacity);
- if (compacted > (int)r->current_capacity)
- resize(r);
-}
-
void *new_resource(struct resource_manager *r, struct resource_id *id)
{
struct resource_id *fresh_id;
@@ -193,8 +125,8 @@ void *new_resource(struct resource_manager *r, struct resource_id *id)
if (r->resource_count + 1 > r->max_capacity)
return NULL;
- if (r->resource_count + 1 >= r->current_capacity)
- compact_or_resize(r);
+ if (r->resource_count + 1 > r->current_capacity)
+ resize(r);
fresh_id = &r->ids[r->resource_count];
@@ -207,7 +139,13 @@ void *new_resource(struct resource_manager *r, struct resource_id *id)
}
void *get_resource(struct resource_manager *r, struct resource_id *id) {
- refresh_id(r, id, id);
+ if (id->generation == 0)
+ return NULL;
+
+ enum refresh_status res = refresh_id(r, id, id);
+
+ if (res == RESOURCE_DELETED)
+ return NULL;
return index_resource(r, id->index);
}
@@ -217,23 +155,24 @@ void destroy_resource(struct resource_manager *r, struct resource_id *id) {
if (is_resource_destroyed(id))
return;
- int res = refresh_id(r, id, id);
+ enum refresh_status res = refresh_id(r, id, id);
// entity already deleted
- if (res == 0) {
+ debug("refresh res %d uuid %llu gen %d index %d\n", res,
+ id->uuid, id->generation, id->index);
+
+ if (res == RESOURCE_DELETED) {
id->generation = 0;
return;
}
- // generation 0 means destroyed
- r->ids[id->index].generation = 0;
- r->ids[id->index].index = -1;
- r->ids[id->index].uuid = -1;
+ r->resource_count--;
+ r->generation++;
- // clear the user's id as well, since it's no longer valid
- id->generation = 0;
- id->uuid = -1;
- id->index = -1;
+ memmove(index_resource(r, id->index),
+ index_resource(r, id->index+1),
+ r->elem_size * r->resource_count);
- /* memmove(index_resource(r, id->index), */
- /* index_resource(r, id->index+1), r->resource_count -) */
+ memmove(&r->ids[id->index],
+ &r->ids[id->index+1],
+ sizeof(*r->ids) * r->resource_count);
}
diff --git a/src/resource.h b/src/resource.h
@@ -4,6 +4,12 @@
#include "common.h"
+enum refresh_status {
+ RESOURCE_DELETED,
+ REFRESH_NOT_NEEDED,
+ REFRESHED_ID
+};
+
struct resource_id {
u64 uuid;
u32 index;
@@ -16,6 +22,7 @@ struct resource_manager {
u32 resource_count;
u32 generation;
u32 elem_size;
+ u32 slots_used;
u32 max_capacity;
u32 current_capacity;
};
diff --git a/test/test_resource.c b/test/test_resource.c
@@ -7,28 +7,40 @@
void test_compact()
{
+ printf("test_compact\n");
struct resource_manager r;
struct resource_id id, first_id;
int *p;
init_resource_manager(&r, sizeof(int), 2, 4);
+
p = new_resource(&r, &first_id);
+ assert(r.resource_count == 1);
*p = 11;
+
p = new_resource(&r, &id);
*p = 22;
- assert(r.current_capacity == 2);
- destroy_resource(&r, &first_id);
assert(r.resource_count == 2);
+
+ destroy_resource(&r, &first_id);
+ assert(r.resource_count == 1);
+ assert(get_resource(&r, &first_id) == NULL);
+ assert(*(int*)get_resource(&r, &id) == 22);
+
new_resource(&r, &id);
assert(r.resource_count == 2);
assert(r.current_capacity == 2);
+
new_resource(&r, &id);
- assert(r.current_capacity == 4);
+ assert(r.resource_count == 3);
+ assert(r.current_capacity >= 3);
}
void test_int_resource_manager()
{
- struct resource_manager r;
+ printf("test_int_resource_manager\n");
+ struct resource_manager r
+;
struct resource_id id, first_id;
int *p;
// 2 item case
@@ -55,6 +67,7 @@ void test_int_resource_manager()
void test_entity_system()
{
+ printf("test_entity_system\n");
u32 count;
struct entity *ent, *ents;
entity_id ent_id;
@@ -79,14 +92,15 @@ void test_entity_system()
void test_dynamic_model_manager()
{
+ printf("test_dynamic_model_manager\n");
init_model_manager();
}
int main(int argc, char *argv[])
{
- /* test_int_resource_manager(); */
+ test_int_resource_manager();
test_compact();
- /* test_dynamic_model_manager(); */
+ test_dynamic_model_manager();
test_entity_system();
return 0;