# HG changeset patch # User John Tsiombikas # Date 1391234528 -7200 # Node ID bd9b4ff19c93132de2b85413c50f44c975a353ac # Parent eadf99551730c603210f6dbc575633b0e1bf543e more stuff diff -r eadf99551730 -r bd9b4ff19c93 Makefile --- a/Makefile Fri Jan 31 16:32:02 2014 +0200 +++ b/Makefile Sat Feb 01 08:02:08 2014 +0200 @@ -11,7 +11,9 @@ api_major = 0 api_minor = 1 -CFLAGS = -pedantic -Wall -g +dbg = -g + +CFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) ifeq ($(shell uname -s), Darwin) lib_so = lib$(name).dylib diff -r eadf99551730 -r bd9b4ff19c93 src/dynarr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dynarr.c Sat Feb 01 08:02:08 2014 +0200 @@ -0,0 +1,124 @@ +#include +#include +#include +#include "dynarr.h" + +/* The array descriptor keeps auxilliary information needed to manipulate + * the dynamic array. It's allocated adjacent to the array buffer. + */ +struct arrdesc { + int nelem, szelem; + int max_elem; + int bufsz; /* not including the descriptor */ +}; + +#define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc))) + +void *dynarr_alloc(int elem, int szelem) +{ + struct arrdesc *desc; + + if(!(desc = malloc(elem * szelem + sizeof *desc))) { + return 0; + } + desc->nelem = desc->max_elem = elem; + desc->szelem = szelem; + desc->bufsz = elem * szelem; + return (char*)desc + sizeof *desc; +} + +void dynarr_free(void *da) +{ + if(da) { + free(DESC(da)); + } +} + +void *dynarr_resize(void *da, int elem) +{ + int newsz; + void *tmp; + struct arrdesc *desc; + + if(!da) return 0; + desc = DESC(da); + + newsz = desc->szelem * elem; + + if(!(tmp = realloc(desc, newsz + sizeof *desc))) { + return 0; + } + desc = tmp; + + desc->nelem = desc->max_elem = elem; + desc->bufsz = newsz; + return (char*)desc + sizeof *desc; +} + +int dynarr_empty(void *da) +{ + return DESC(da)->nelem ? 0 : 1; +} + +int dynarr_size(void *da) +{ + return DESC(da)->nelem; +} + + +/* stack semantics */ +void *dynarr_push(void *da, void *item) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(nelem >= desc->max_elem) { + /* need to resize */ + struct arrdesc *tmp; + int newsz = desc->max_elem ? desc->max_elem * 2 : 1; + + if(!(tmp = dynarr_resize(da, newsz))) { + fprintf(stderr, "failed to resize\n"); + return da; + } + da = tmp; + desc = DESC(da); + desc->nelem = nelem; + } + + if(item) { + memcpy((char*)da + desc->nelem++ * desc->szelem, item, desc->szelem); + } + return da; +} + +void *dynarr_pop(void *da) +{ + struct arrdesc *desc; + int nelem; + + desc = DESC(da); + nelem = desc->nelem; + + if(!nelem) return da; + + if(nelem <= desc->max_elem / 3) { + /* reclaim space */ + struct arrdesc *tmp; + int newsz = desc->max_elem / 2; + + if(!(tmp = dynarr_resize(da, newsz))) { + fprintf(stderr, "failed to resize\n"); + return da; + } + da = tmp; + desc = DESC(da); + desc->nelem = nelem; + } + desc->nelem--; + + return da; +} diff -r eadf99551730 -r bd9b4ff19c93 src/dynarr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dynarr.h Sat Feb 01 08:02:08 2014 +0200 @@ -0,0 +1,16 @@ +#ifndef DYNARR_H_ +#define DYNARR_H_ + +void *dynarr_alloc(int elem, int szelem); +void dynarr_free(void *da); +void *dynarr_resize(void *da, int elem); + +int dynarr_empty(void *da); +int dynarr_size(void *da); + +/* stack semantics */ +void *dynarr_push(void *da, void *item); +void *dynarr_pop(void *da); + + +#endif /* DYNARR_H_ */ diff -r eadf99551730 -r bd9b4ff19c93 src/resman.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/resman.c Sat Feb 01 08:02:08 2014 +0200 @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include "resman.h" +#include "dynarr.h" +#include "threadpool.h" + +struct resource { + char *name; + void *data; +}; + +struct resman { + struct resource *res; + + resman_load_func load_func; + resman_create_func create_func; + resman_update_func update_func; + resman_destroy_func destroy_func; + + void *load_func_cls; + void *create_func_cls; + void *update_func_cls; + void *destroy_func_cls; +}; + + +static int find_resource(struct resman *rman, const char *fname); +static int add_resource(struct resman *rman, const char *fname, void *data); + +struct resman *resman_create(void) +{ + struct resman *rman = malloc(sizeof *rman); + if(resman_init(rman) == -1) { + free(rman); + return 0; + } + return rman; +} + +void resman_free(struct resman *rman) +{ + resman_destroy(rman); + free(rman); +} + +int resman_init(struct resman *rman) +{ + memset(rman, 0, sizeof *rman); + + if(!(rman->res = dynarr_alloc(0, sizeof *rman->res))) { + return -1; + } + + return 0; +} + +void resman_destroy(struct resman *rman) +{ + int i; + if(!rman) return; + + for(i=0; ires); i++) { + if(rman->destroy_func) { + rman->destroy_func(rman->res[i].data, rman->destroy_func_cls); + } + } + dynarr_free(rman->res); +} + + +void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls) +{ + rman->load_func = func; + rman->load_func_cls = cls; +} + +void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls) +{ + rman->create_func = func; + rman->create_func_cls = cls; +} + +void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls) +{ + rman->update_func = func; + rman->update_func_cls = cls; +} + +void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls) +{ + rman->destroy_func = func; + rman->destroy_func_cls = cls; +} + +int resman_lookup(struct resman *rman, const char *fname, void *data) +{ + int ridx; + + if((ridx = find_resource(rman, fname)) != -1) { + return ridx; + } + + /* resource not found, create a new one and start a loading job */ + return add_resource(rman, fname, data); +} + +void resman_wait(struct resman *rman, int id) +{ + /* TODO */ +} + +int resman_poll(struct resman *rman) +{ + /* TODO */ + return 0; +} + + +void resman_set_res_data(struct resman *rman, int res_id, void *data) +{ + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { + rman->res[res_id].data = data; + } +} + +void *resman_get_res_data(struct resman *rman, int res_id) +{ + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { + return rman->res[res_id].data; + } + return 0; +} + +static int find_resource(struct resman *rman, const char *fname) +{ + int i, sz = dynarr_size(rman->res); + + for(i=0; ires[i].name, fname) == 0) { + return i; + } + } + return -1; +} + +static int add_resource(struct resman *rman, const char *fname, void *data) +{ + int idx = dynarr_size(rman->res); + + struct resource *tmp = dynarr_push(rman->res, 0); + if(!tmp) { + return -1; + } + rman->res = tmp; + + rman->res[idx].name = strdup(fname); + assert(rman->res[idx].name); + + rman->res[idx].data = data; + + /* TODO start a loading job ... */ + + return idx; +} diff -r eadf99551730 -r bd9b4ff19c93 src/resman.h --- a/src/resman.h Fri Jan 31 16:32:02 2014 +0200 +++ b/src/resman.h Sat Feb 01 08:02:08 2014 +0200 @@ -1,25 +1,29 @@ #ifndef RESOURCE_MANAGER_H_ #define RESOURCE_MANAGER_H_ +/* load callback: everything or just file read/parse stage + * create callback: second-stage callback for first creation + * update callback: second-stage callback for reload + */ +typedef int (*resman_load_func)(const char *fname, void *data, void *closure); +typedef int (*resman_create_func)(void *data, void *closure); +typedef int (*resman_update_func)(void *data, void *closure); +typedef void (*resman_destroy_func)(void *data, void *closure); + struct resman; +struct resman *resman_create(void); +void resman_free(struct resman *rman); + int resman_init(struct resman *rman); void resman_destroy(struct resman *rman); -/* The load callback will be called to load a data file. It may be called in the - * context of a different loading thread. - */ -/*void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls);*/ +void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls); +void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls); +void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls); +void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls); -/* The "done" callback will be called in the context of the main thread, whenever a - * file was sucessfully loaded, or an error occured. - * It's first argument (status) is set to whatever the load function returned, and its - * closure pointer is the closure ... - */ -/*void resman_set_done_func(struct resman *rman, resman_done_func_t func);*/ - - -int resman_lookup(struct resman *rman, const char *fname, void *cls); +int resman_lookup(struct resman *rman, const char *fname, void *data); void resman_wait(struct resman *rman, int id); int resman_poll(struct resman *rman); diff -r eadf99551730 -r bd9b4ff19c93 src/threadpool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/threadpool.h Sat Feb 01 08:02:08 2014 +0200 @@ -0,0 +1,16 @@ +#ifndef THREAD_POOL_H_ +#define THREAD_POOL_H_ + +struct thread_pool; + +typedef void (*tpool_work_func)(void*); + +#define TPOOL_AUTO 0 +int tpool_init(struct thread_pool *tpool, int num_threads); +void tpool_destroy(struct thread_pool *tpool); + +void tpool_set_work_func(struct thread_pool *tpool, tpool_work_func func, void *cls); + +/* TODO cont. */ + +#endif /* THREAD_POOL_H_ */