libresman

diff src/resman.c @ 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 bd9b4ff19c93
children bebc065a941f
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 +}