libresman

changeset 10:4d18498a0078

moved the resource manager a bit further
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 05 Feb 2014 02:01:49 +0200
parents 03f3de659c32
children bebc065a941f
files src/resman.c src/resman.h src/threadpool.c src/threadpool.h
diffstat 4 files changed, 98 insertions(+), 21 deletions(-) [+]
line diff
     1.1 --- a/src/resman.c	Tue Feb 04 05:42:31 2014 +0200
     1.2 +++ b/src/resman.c	Wed Feb 05 02:01:49 2014 +0200
     1.3 @@ -2,6 +2,7 @@
     1.4  #include <stdlib.h>
     1.5  #include <string.h>
     1.6  #include <assert.h>
     1.7 +#include <pthread.h>
     1.8  #include "resman.h"
     1.9  #include "dynarr.h"
    1.10  #include "threadpool.h"
    1.11 @@ -9,25 +10,29 @@
    1.12  struct resource {
    1.13  	char *name;
    1.14  	void *data;
    1.15 +	int result;	/* last callback-reported success/fail code */
    1.16 +
    1.17 +	int done_pending;
    1.18 +	pthread_mutex_t done_lock;
    1.19  };
    1.20  
    1.21  struct resman {
    1.22  	struct resource *res;
    1.23 +	struct thread_pool *tpool;
    1.24  
    1.25  	resman_load_func load_func;
    1.26 -	resman_create_func create_func;
    1.27 -	resman_update_func update_func;
    1.28 +	resman_done_func done_func;
    1.29  	resman_destroy_func destroy_func;
    1.30  
    1.31  	void *load_func_cls;
    1.32 -	void *create_func_cls;
    1.33 -	void *update_func_cls;
    1.34 +	void *done_func_cls;
    1.35  	void *destroy_func_cls;
    1.36  };
    1.37  
    1.38  
    1.39  static int find_resource(struct resman *rman, const char *fname);
    1.40  static int add_resource(struct resman *rman, const char *fname, void *data);
    1.41 +static void work_func(void *data, void *cls);
    1.42  
    1.43  struct resman *resman_create(void)
    1.44  {
    1.45 @@ -49,7 +54,13 @@
    1.46  {
    1.47  	memset(rman, 0, sizeof *rman);
    1.48  
    1.49 +	if(!(rman->tpool = tpool_create(TPOOL_AUTO))) {
    1.50 +		return -1;
    1.51 +	}
    1.52 +	tpool_set_work_func(rman->tpool, work_func, rman);
    1.53 +
    1.54  	if(!(rman->res = dynarr_alloc(0, sizeof *rman->res))) {
    1.55 +		tpool_free(rman->tpool);
    1.56  		return -1;
    1.57  	}
    1.58  
    1.59 @@ -67,6 +78,8 @@
    1.60  		}
    1.61  	}
    1.62  	dynarr_free(rman->res);
    1.63 +
    1.64 +	tpool_free(rman->tpool);
    1.65  }
    1.66  
    1.67  
    1.68 @@ -76,16 +89,10 @@
    1.69  	rman->load_func_cls = cls;
    1.70  }
    1.71  
    1.72 -void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls)
    1.73 +void resman_set_done_func(struct resman *rman, resman_done_func func, void *cls)
    1.74  {
    1.75 -	rman->create_func = func;
    1.76 -	rman->create_func_cls = cls;
    1.77 -}
    1.78 -
    1.79 -void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls)
    1.80 -{
    1.81 -	rman->update_func = func;
    1.82 -	rman->update_func_cls = cls;
    1.83 +	rman->done_func = func;
    1.84 +	rman->done_func_cls = cls;
    1.85  }
    1.86  
    1.87  void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls)
    1.88 @@ -113,7 +120,30 @@
    1.89  
    1.90  int resman_poll(struct resman *rman)
    1.91  {
    1.92 -	/* TODO */
    1.93 +	int i, num_res;
    1.94 +
    1.95 +	if(!rman->done_func) {
    1.96 +		return 0;	/* no done callback; there's no point in checking anything */
    1.97 +	}
    1.98 +
    1.99 +	num_res = dynarr_size(rman->res);
   1.100 +	for(i=0; i<num_res; i++) {
   1.101 +		struct resource *res = rman->res + i;
   1.102 +		int last_result;
   1.103 +
   1.104 +		pthread_mutex_lock(&res->done_lock);
   1.105 +		if(!res->done_pending) {
   1.106 +			pthread_mutex_unlock(&res->done_lock);
   1.107 +			continue;
   1.108 +		}
   1.109 +
   1.110 +		/* so a done callback *is* pending... */
   1.111 +		res->done_pending = 0;
   1.112 +		last_result = res->result;
   1.113 +		pthread_mutex_unlock(&res->done_lock);
   1.114 +
   1.115 +		rman->done_func(last_result, res->data, rman->done_func_cls);
   1.116 +	}
   1.117  	return 0;
   1.118  }
   1.119  
   1.120 @@ -133,6 +163,14 @@
   1.121  	return 0;
   1.122  }
   1.123  
   1.124 +int resman_get_res_error(struct resman *rman, int res_id)
   1.125 +{
   1.126 +	if(res_id >= 0 && res_id < dynarr_size(rman->res)) {
   1.127 +		return rman->res[res_id].result;
   1.128 +	}
   1.129 +	return -1;
   1.130 +}
   1.131 +
   1.132  static int find_resource(struct resman *rman, const char *fname)
   1.133  {
   1.134  	int i, sz = dynarr_size(rman->res);
   1.135 @@ -160,7 +198,22 @@
   1.136  
   1.137  	rman->res[idx].data = data;
   1.138  
   1.139 -	/* TODO start a loading job ... */
   1.140 +	/* start a loading job ... */
   1.141 +	tpool_add_work(rman->tpool, rman->res + idx);
   1.142  
   1.143  	return idx;
   1.144  }
   1.145 +
   1.146 +/* this is the background work function which handles all the
   1.147 + * first-stage resource loading...
   1.148 + */
   1.149 +static void work_func(void *data, void *cls)
   1.150 +{
   1.151 +	struct resource *res = data;
   1.152 +	struct resman *rman = cls;
   1.153 +
   1.154 +	res->result = rman->load_func(res->name, res->data, rman->load_func_cls);
   1.155 +	pthread_mutex_lock(&res->done_lock);
   1.156 +	res->done_pending = 1;
   1.157 +	pthread_mutex_unlock(&res->done_lock);
   1.158 +}
     2.1 --- a/src/resman.h	Tue Feb 04 05:42:31 2014 +0200
     2.2 +++ b/src/resman.h	Wed Feb 05 02:01:49 2014 +0200
     2.3 @@ -2,12 +2,11 @@
     2.4  #define RESOURCE_MANAGER_H_
     2.5  
     2.6  /* load callback: everything or just file read/parse stage
     2.7 - * create callback: second-stage callback for first creation
     2.8 - * update callback: second-stage callback for reload
     2.9 + * done callback: second-stage callback, called in the context of the
    2.10 + *                user thread, after the load callback returns
    2.11   */
    2.12  typedef int (*resman_load_func)(const char *fname, void *data, void *closure);
    2.13 -typedef int (*resman_create_func)(void *data, void *closure);
    2.14 -typedef int (*resman_update_func)(void *data, void *closure);
    2.15 +typedef int (*resman_done_func)(int result, void *data, void *closure);
    2.16  typedef void (*resman_destroy_func)(void *data, void *closure);
    2.17  
    2.18  struct resman;
    2.19 @@ -23,8 +22,7 @@
    2.20  void resman_destroy(struct resman *rman);
    2.21  
    2.22  void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls);
    2.23 -void resman_set_create_func(struct resman *rman, resman_create_func func, void *cls);
    2.24 -void resman_set_update_func(struct resman *rman, resman_update_func func, void *cls);
    2.25 +void resman_set_done_func(struct resman *rman, resman_done_func func, void *cls);
    2.26  void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls);
    2.27  
    2.28  int resman_lookup(struct resman *rman, const char *fname, void *data);
    2.29 @@ -35,6 +33,8 @@
    2.30  void resman_set_res_data(struct resman *rman, int res_id, void *data);
    2.31  void *resman_get_res_data(struct resman *rman, int res_id);
    2.32  
    2.33 +int resman_get_res_error(struct resman *rman, int res_id);
    2.34 +
    2.35  #ifdef __cplusplus
    2.36  }
    2.37  #endif
     3.1 --- a/src/threadpool.c	Tue Feb 04 05:42:31 2014 +0200
     3.2 +++ b/src/threadpool.c	Wed Feb 05 02:01:49 2014 +0200
     3.3 @@ -69,6 +69,27 @@
     3.4  	pthread_cond_destroy(&tpool->work_cond);
     3.5  }
     3.6  
     3.7 +struct thread_pool *tpool_create(int num_threads)
     3.8 +{
     3.9 +	struct thread_pool *tpool = malloc(sizeof *tpool);
    3.10 +	if(!tpool) {
    3.11 +		return 0;
    3.12 +	}
    3.13 +	if(tpool_init(tpool, num_threads) == -1) {
    3.14 +		free(tpool);
    3.15 +		return 0;
    3.16 +	}
    3.17 +	return tpool;
    3.18 +}
    3.19 +
    3.20 +void tpool_free(struct thread_pool *tpool)
    3.21 +{
    3.22 +	if(tpool) {
    3.23 +		tpool_destroy(tpool);
    3.24 +		free(tpool);
    3.25 +	}
    3.26 +}
    3.27 +
    3.28  void tpool_set_work_func(struct thread_pool *tpool, tpool_work_func func, void *cls)
    3.29  {
    3.30  	tpool->work_func = func;
     4.1 --- a/src/threadpool.h	Tue Feb 04 05:42:31 2014 +0200
     4.2 +++ b/src/threadpool.h	Wed Feb 05 02:01:49 2014 +0200
     4.3 @@ -9,6 +9,9 @@
     4.4  int tpool_init(struct thread_pool *tpool, int num_threads);
     4.5  void tpool_destroy(struct thread_pool *tpool);
     4.6  
     4.7 +struct thread_pool *tpool_create(int num_threads);
     4.8 +void tpool_free(struct thread_pool *tpool);
     4.9 +
    4.10  void tpool_set_work_func(struct thread_pool *tpool, tpool_work_func func, void *cls);
    4.11  
    4.12  int tpool_add_work(struct thread_pool *tpool, void *data);