libresman
changeset 5:bd9b4ff19c93
more stuff
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 08:02:08 +0200 |
parents | eadf99551730 |
children | 410c19c735b2 |
files | Makefile src/dynarr.c src/dynarr.h src/resman.c src/resman.h src/threadpool.h |
diffstat | 6 files changed, 342 insertions(+), 14 deletions(-) [+] |
line diff
1.1 --- a/Makefile Fri Jan 31 16:32:02 2014 +0200 1.2 +++ b/Makefile Sat Feb 01 08:02:08 2014 +0200 1.3 @@ -11,7 +11,9 @@ 1.4 api_major = 0 1.5 api_minor = 1 1.6 1.7 -CFLAGS = -pedantic -Wall -g 1.8 +dbg = -g 1.9 + 1.10 +CFLAGS = -pedantic -Wall $(dbg) $(opt) $(pic) 1.11 1.12 ifeq ($(shell uname -s), Darwin) 1.13 lib_so = lib$(name).dylib
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/dynarr.c Sat Feb 01 08:02:08 2014 +0200 2.3 @@ -0,0 +1,124 @@ 2.4 +#include <stdio.h> 2.5 +#include <stdlib.h> 2.6 +#include <string.h> 2.7 +#include "dynarr.h" 2.8 + 2.9 +/* The array descriptor keeps auxilliary information needed to manipulate 2.10 + * the dynamic array. It's allocated adjacent to the array buffer. 2.11 + */ 2.12 +struct arrdesc { 2.13 + int nelem, szelem; 2.14 + int max_elem; 2.15 + int bufsz; /* not including the descriptor */ 2.16 +}; 2.17 + 2.18 +#define DESC(x) ((struct arrdesc*)((char*)(x) - sizeof(struct arrdesc))) 2.19 + 2.20 +void *dynarr_alloc(int elem, int szelem) 2.21 +{ 2.22 + struct arrdesc *desc; 2.23 + 2.24 + if(!(desc = malloc(elem * szelem + sizeof *desc))) { 2.25 + return 0; 2.26 + } 2.27 + desc->nelem = desc->max_elem = elem; 2.28 + desc->szelem = szelem; 2.29 + desc->bufsz = elem * szelem; 2.30 + return (char*)desc + sizeof *desc; 2.31 +} 2.32 + 2.33 +void dynarr_free(void *da) 2.34 +{ 2.35 + if(da) { 2.36 + free(DESC(da)); 2.37 + } 2.38 +} 2.39 + 2.40 +void *dynarr_resize(void *da, int elem) 2.41 +{ 2.42 + int newsz; 2.43 + void *tmp; 2.44 + struct arrdesc *desc; 2.45 + 2.46 + if(!da) return 0; 2.47 + desc = DESC(da); 2.48 + 2.49 + newsz = desc->szelem * elem; 2.50 + 2.51 + if(!(tmp = realloc(desc, newsz + sizeof *desc))) { 2.52 + return 0; 2.53 + } 2.54 + desc = tmp; 2.55 + 2.56 + desc->nelem = desc->max_elem = elem; 2.57 + desc->bufsz = newsz; 2.58 + return (char*)desc + sizeof *desc; 2.59 +} 2.60 + 2.61 +int dynarr_empty(void *da) 2.62 +{ 2.63 + return DESC(da)->nelem ? 0 : 1; 2.64 +} 2.65 + 2.66 +int dynarr_size(void *da) 2.67 +{ 2.68 + return DESC(da)->nelem; 2.69 +} 2.70 + 2.71 + 2.72 +/* stack semantics */ 2.73 +void *dynarr_push(void *da, void *item) 2.74 +{ 2.75 + struct arrdesc *desc; 2.76 + int nelem; 2.77 + 2.78 + desc = DESC(da); 2.79 + nelem = desc->nelem; 2.80 + 2.81 + if(nelem >= desc->max_elem) { 2.82 + /* need to resize */ 2.83 + struct arrdesc *tmp; 2.84 + int newsz = desc->max_elem ? desc->max_elem * 2 : 1; 2.85 + 2.86 + if(!(tmp = dynarr_resize(da, newsz))) { 2.87 + fprintf(stderr, "failed to resize\n"); 2.88 + return da; 2.89 + } 2.90 + da = tmp; 2.91 + desc = DESC(da); 2.92 + desc->nelem = nelem; 2.93 + } 2.94 + 2.95 + if(item) { 2.96 + memcpy((char*)da + desc->nelem++ * desc->szelem, item, desc->szelem); 2.97 + } 2.98 + return da; 2.99 +} 2.100 + 2.101 +void *dynarr_pop(void *da) 2.102 +{ 2.103 + struct arrdesc *desc; 2.104 + int nelem; 2.105 + 2.106 + desc = DESC(da); 2.107 + nelem = desc->nelem; 2.108 + 2.109 + if(!nelem) return da; 2.110 + 2.111 + if(nelem <= desc->max_elem / 3) { 2.112 + /* reclaim space */ 2.113 + struct arrdesc *tmp; 2.114 + int newsz = desc->max_elem / 2; 2.115 + 2.116 + if(!(tmp = dynarr_resize(da, newsz))) { 2.117 + fprintf(stderr, "failed to resize\n"); 2.118 + return da; 2.119 + } 2.120 + da = tmp; 2.121 + desc = DESC(da); 2.122 + desc->nelem = nelem; 2.123 + } 2.124 + desc->nelem--; 2.125 + 2.126 + return da; 2.127 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/dynarr.h Sat Feb 01 08:02:08 2014 +0200 3.3 @@ -0,0 +1,16 @@ 3.4 +#ifndef DYNARR_H_ 3.5 +#define DYNARR_H_ 3.6 + 3.7 +void *dynarr_alloc(int elem, int szelem); 3.8 +void dynarr_free(void *da); 3.9 +void *dynarr_resize(void *da, int elem); 3.10 + 3.11 +int dynarr_empty(void *da); 3.12 +int dynarr_size(void *da); 3.13 + 3.14 +/* stack semantics */ 3.15 +void *dynarr_push(void *da, void *item); 3.16 +void *dynarr_pop(void *da); 3.17 + 3.18 + 3.19 +#endif /* DYNARR_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/resman.c Sat Feb 01 08:02:08 2014 +0200 4.3 @@ -0,0 +1,166 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <string.h> 4.7 +#include <assert.h> 4.8 +#include "resman.h" 4.9 +#include "dynarr.h" 4.10 +#include "threadpool.h" 4.11 + 4.12 +struct resource { 4.13 + char *name; 4.14 + void *data; 4.15 +}; 4.16 + 4.17 +struct resman { 4.18 + struct resource *res; 4.19 + 4.20 + resman_load_func load_func; 4.21 + resman_create_func create_func; 4.22 + resman_update_func update_func; 4.23 + resman_destroy_func destroy_func; 4.24 + 4.25 + void *load_func_cls; 4.26 + void *create_func_cls; 4.27 + void *update_func_cls; 4.28 + void *destroy_func_cls; 4.29 +}; 4.30 + 4.31 + 4.32 +static int find_resource(struct resman *rman, const char *fname); 4.33 +static int add_resource(struct resman *rman, const char *fname, void *data); 4.34 + 4.35 +struct resman *resman_create(void) 4.36 +{ 4.37 + struct resman *rman = malloc(sizeof *rman); 4.38 + if(resman_init(rman) == -1) { 4.39 + free(rman); 4.40 + return 0; 4.41 + } 4.42 + return rman; 4.43 +} 4.44 + 4.45 +void resman_free(struct resman *rman) 4.46 +{ 4.47 + resman_destroy(rman); 4.48 + free(rman); 4.49 +} 4.50 + 4.51 +int resman_init(struct resman *rman) 4.52 +{ 4.53 + memset(rman, 0, sizeof *rman); 4.54 + 4.55 + if(!(rman->res = dynarr_alloc(0, sizeof *rman->res))) { 4.56 + return -1; 4.57 + } 4.58 + 4.59 + return 0; 4.60 +} 4.61 + 4.62 +void resman_destroy(struct resman *rman) 4.63 +{ 4.64 + int i; 4.65 + if(!rman) return; 4.66 + 4.67 + for(i=0; i<dynarr_size(rman->res); i++) { 4.68 + if(rman->destroy_func) { 4.69 + rman->destroy_func(rman->res[i].data, rman->destroy_func_cls); 4.70 + } 4.71 + } 4.72 + dynarr_free(rman->res); 4.73 +} 4.74 + 4.75 + 4.76 +void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls) 4.77 +{ 4.78 + rman->load_func = func; 4.79 + rman->load_func_cls = cls; 4.80 +} 4.81 + 4.82 +void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls) 4.83 +{ 4.84 + rman->create_func = func; 4.85 + rman->create_func_cls = cls; 4.86 +} 4.87 + 4.88 +void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls) 4.89 +{ 4.90 + rman->update_func = func; 4.91 + rman->update_func_cls = cls; 4.92 +} 4.93 + 4.94 +void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls) 4.95 +{ 4.96 + rman->destroy_func = func; 4.97 + rman->destroy_func_cls = cls; 4.98 +} 4.99 + 4.100 +int resman_lookup(struct resman *rman, const char *fname, void *data) 4.101 +{ 4.102 + int ridx; 4.103 + 4.104 + if((ridx = find_resource(rman, fname)) != -1) { 4.105 + return ridx; 4.106 + } 4.107 + 4.108 + /* resource not found, create a new one and start a loading job */ 4.109 + return add_resource(rman, fname, data); 4.110 +} 4.111 + 4.112 +void resman_wait(struct resman *rman, int id) 4.113 +{ 4.114 + /* TODO */ 4.115 +} 4.116 + 4.117 +int resman_poll(struct resman *rman) 4.118 +{ 4.119 + /* TODO */ 4.120 + return 0; 4.121 +} 4.122 + 4.123 + 4.124 +void resman_set_res_data(struct resman *rman, int res_id, void *data) 4.125 +{ 4.126 + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 4.127 + rman->res[res_id].data = data; 4.128 + } 4.129 +} 4.130 + 4.131 +void *resman_get_res_data(struct resman *rman, int res_id) 4.132 +{ 4.133 + if(res_id >= 0 && res_id < dynarr_size(rman->res)) { 4.134 + return rman->res[res_id].data; 4.135 + } 4.136 + return 0; 4.137 +} 4.138 + 4.139 +static int find_resource(struct resman *rman, const char *fname) 4.140 +{ 4.141 + int i, sz = dynarr_size(rman->res); 4.142 + 4.143 + for(i=0; i<sz; i++) { 4.144 + if(strcmp(rman->res[i].name, fname) == 0) { 4.145 + return i; 4.146 + } 4.147 + } 4.148 + return -1; 4.149 +} 4.150 + 4.151 +static int add_resource(struct resman *rman, const char *fname, void *data) 4.152 +{ 4.153 + int idx = dynarr_size(rman->res); 4.154 + 4.155 + struct resource *tmp = dynarr_push(rman->res, 0); 4.156 + if(!tmp) { 4.157 + return -1; 4.158 + } 4.159 + rman->res = tmp; 4.160 + 4.161 + rman->res[idx].name = strdup(fname); 4.162 + assert(rman->res[idx].name); 4.163 + 4.164 + rman->res[idx].data = data; 4.165 + 4.166 + /* TODO start a loading job ... */ 4.167 + 4.168 + return idx; 4.169 +}
5.1 --- a/src/resman.h Fri Jan 31 16:32:02 2014 +0200 5.2 +++ b/src/resman.h Sat Feb 01 08:02:08 2014 +0200 5.3 @@ -1,25 +1,29 @@ 5.4 #ifndef RESOURCE_MANAGER_H_ 5.5 #define RESOURCE_MANAGER_H_ 5.6 5.7 +/* load callback: everything or just file read/parse stage 5.8 + * create callback: second-stage callback for first creation 5.9 + * update callback: second-stage callback for reload 5.10 + */ 5.11 +typedef int (*resman_load_func)(const char *fname, void *data, void *closure); 5.12 +typedef int (*resman_create_func)(void *data, void *closure); 5.13 +typedef int (*resman_update_func)(void *data, void *closure); 5.14 +typedef void (*resman_destroy_func)(void *data, void *closure); 5.15 + 5.16 struct resman; 5.17 5.18 +struct resman *resman_create(void); 5.19 +void resman_free(struct resman *rman); 5.20 + 5.21 int resman_init(struct resman *rman); 5.22 void resman_destroy(struct resman *rman); 5.23 5.24 -/* The load callback will be called to load a data file. It may be called in the 5.25 - * context of a different loading thread. 5.26 - */ 5.27 -/*void resman_set_load_func(struct resman *rman, resman_load_func_t func, void *cls);*/ 5.28 +void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls); 5.29 +void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls); 5.30 +void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls); 5.31 +void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls); 5.32 5.33 -/* The "done" callback will be called in the context of the main thread, whenever a 5.34 - * file was sucessfully loaded, or an error occured. 5.35 - * It's first argument (status) is set to whatever the load function returned, and its 5.36 - * closure pointer is the closure ... 5.37 - */ 5.38 -/*void resman_set_done_func(struct resman *rman, resman_done_func_t func);*/ 5.39 - 5.40 - 5.41 -int resman_lookup(struct resman *rman, const char *fname, void *cls); 5.42 +int resman_lookup(struct resman *rman, const char *fname, void *data); 5.43 void resman_wait(struct resman *rman, int id); 5.44 5.45 int resman_poll(struct resman *rman);
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/threadpool.h Sat Feb 01 08:02:08 2014 +0200 6.3 @@ -0,0 +1,16 @@ 6.4 +#ifndef THREAD_POOL_H_ 6.5 +#define THREAD_POOL_H_ 6.6 + 6.7 +struct thread_pool; 6.8 + 6.9 +typedef void (*tpool_work_func)(void*); 6.10 + 6.11 +#define TPOOL_AUTO 0 6.12 +int tpool_init(struct thread_pool *tpool, int num_threads); 6.13 +void tpool_destroy(struct thread_pool *tpool); 6.14 + 6.15 +void tpool_set_work_func(struct thread_pool *tpool, tpool_work_func func, void *cls); 6.16 + 6.17 +/* TODO cont. */ 6.18 + 6.19 +#endif /* THREAD_POOL_H_ */