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_ */