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