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);