libresman

diff src/resman.c @ 13:a42888d26839

bit more progress...
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 08 Feb 2014 07:41:39 +0200
parents 84f55eab27cb
children 2fcd1fbb0d18
line diff
     1.1 --- a/src/resman.c	Sat Feb 08 04:21:08 2014 +0200
     1.2 +++ b/src/resman.c	Sat Feb 08 07:41:39 2014 +0200
     1.3 @@ -21,6 +21,8 @@
     1.4  	struct resource **res;
     1.5  	struct thread_pool *tpool;
     1.6  
     1.7 +	pthread_mutex_t lock;	/* global resman lock (for res array changes) */
     1.8 +
     1.9  	resman_load_func load_func;
    1.10  	resman_done_func done_func;
    1.11  	resman_destroy_func destroy_func;
    1.12 @@ -33,6 +35,7 @@
    1.13  
    1.14  static int find_resource(struct resman *rman, const char *fname);
    1.15  static int add_resource(struct resman *rman, const char *fname, void *data);
    1.16 +static void remove_resource(struct resman *rman, int idx);
    1.17  static void work_func(void *data, void *cls);
    1.18  
    1.19  struct resman *resman_create(void)
    1.20 @@ -65,6 +68,8 @@
    1.21  		return -1;
    1.22  	}
    1.23  
    1.24 +	pthread_mutex_init(&rman->lock, 0);
    1.25 +
    1.26  	return 0;
    1.27  }
    1.28  
    1.29 @@ -82,6 +87,8 @@
    1.30  	dynarr_free(rman->res);
    1.31  
    1.32  	tpool_free(rman->tpool);
    1.33 +
    1.34 +	pthread_mutex_destroy(&rman->lock);
    1.35  }
    1.36  
    1.37  
    1.38 @@ -131,6 +138,9 @@
    1.39  	num_res = dynarr_size(rman->res);
    1.40  	for(i=0; i<num_res; i++) {
    1.41  		struct resource *res = rman->res[i];
    1.42 +		if(!res) {
    1.43 +			continue;
    1.44 +		}
    1.45  
    1.46  		printf("locking mutex %d\n", res->id);
    1.47  		pthread_mutex_lock(&res->done_lock);
    1.48 @@ -142,7 +152,13 @@
    1.49  
    1.50  		/* so a done callback *is* pending... */
    1.51  		res->done_pending = 0;
    1.52 -		rman->done_func(i, rman->done_func_cls);
    1.53 +		if(rman->done_func(i, rman->done_func_cls) == -1) {
    1.54 +			/* done-func returned -1, so let's remove the resource */
    1.55 +			printf("  unlocking mutex %d\n", res->id);
    1.56 +			pthread_mutex_unlock(&res->done_lock);
    1.57 +			remove_resource(rman, i);
    1.58 +			continue;
    1.59 +		}
    1.60  		printf("  unlocking mutex %d\n", res->id);
    1.61  		pthread_mutex_unlock(&res->done_lock);
    1.62  	}
    1.63 @@ -194,31 +210,64 @@
    1.64  
    1.65  static int add_resource(struct resman *rman, const char *fname, void *data)
    1.66  {
    1.67 -	int idx = dynarr_size(rman->res);
    1.68 +	int i, idx = -1, size = dynarr_size(rman->res);
    1.69  	struct resource *res;
    1.70  	struct resource **tmparr;
    1.71  
    1.72 +	/* allocate a new resource */
    1.73  	if(!(res = malloc(sizeof *res))) {
    1.74  		return -1;
    1.75  	}
    1.76 -	res->id = idx;
    1.77 +	memset(res, 0, sizeof *res);
    1.78 +
    1.79  	res->name = strdup(fname);
    1.80  	assert(res->name);
    1.81  	res->data = data;
    1.82 -
    1.83  	pthread_mutex_init(&res->done_lock, 0);
    1.84  
    1.85 -	if(!(tmparr = dynarr_push(rman->res, &res))) {
    1.86 -		free(res);
    1.87 -		return -1;
    1.88 +
    1.89 +	/* check to see if there's an emtpy (previously erased) slot */
    1.90 +	for(i=0; i<size; i++) {
    1.91 +		if(!rman->res[i]) {
    1.92 +			idx = i;
    1.93 +			break;
    1.94 +		}
    1.95  	}
    1.96 -	rman->res = tmparr;
    1.97 +
    1.98 +	if(idx == -1) {
    1.99 +		/* free slot not found, append a new one */
   1.100 +		idx = size;
   1.101 +
   1.102 +		if(!(tmparr = dynarr_push(rman->res, &res))) {
   1.103 +			free(res);
   1.104 +			return -1;
   1.105 +		}
   1.106 +		rman->res = tmparr;
   1.107 +	} else {
   1.108 +		/* free slot found, just use it */
   1.109 +		res = rman->res[idx];
   1.110 +	}
   1.111 +
   1.112 +	res->id = idx;	/* set the resource id */
   1.113  
   1.114  	/* start a loading job ... */
   1.115  	tpool_add_work(rman->tpool, rman->res[idx]);
   1.116  	return idx;
   1.117  }
   1.118  
   1.119 +/* remove a resource and leave the pointer null to reuse the slot */
   1.120 +static void remove_resource(struct resman *rman, int idx)
   1.121 +{
   1.122 +	if(rman->destroy_func) {
   1.123 +		rman->destroy_func(idx, rman->destroy_func_cls);
   1.124 +	}
   1.125 +
   1.126 +	pthread_mutex_destroy(&rman->res[idx]->done_lock);
   1.127 +
   1.128 +	free(rman->res[idx]);
   1.129 +	rman->res[idx] = 0;
   1.130 +}
   1.131 +
   1.132  /* this is the background work function which handles all the
   1.133   * first-stage resource loading...
   1.134   */
   1.135 @@ -228,6 +277,11 @@
   1.136  	struct resman *rman = cls;
   1.137  
   1.138  	res->result = rman->load_func(res->name, res->id, rman->load_func_cls);
   1.139 +	if(res->result == -1 && !rman->done_func) {
   1.140 +		/* if there's no done function and we got an error, remove the resource now */
   1.141 +		remove_resource(rman, res->id);
   1.142 +		return;
   1.143 +	}
   1.144  
   1.145  	printf("locking mutex %d\n", res->id);
   1.146  	pthread_mutex_lock(&res->done_lock);