libresman

annotate src/resman.c @ 11:bebc065a941f

doesn't work yet
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 07 Feb 2014 07:50:02 +0200
parents 4d18498a0078
children 84f55eab27cb
rev   line source
nuclear@5 1 #include <stdio.h>
nuclear@5 2 #include <stdlib.h>
nuclear@5 3 #include <string.h>
nuclear@5 4 #include <assert.h>
nuclear@10 5 #include <pthread.h>
nuclear@5 6 #include "resman.h"
nuclear@5 7 #include "dynarr.h"
nuclear@5 8 #include "threadpool.h"
nuclear@5 9
nuclear@5 10 struct resource {
nuclear@11 11 int id;
nuclear@5 12 char *name;
nuclear@5 13 void *data;
nuclear@10 14 int result; /* last callback-reported success/fail code */
nuclear@10 15
nuclear@10 16 int done_pending;
nuclear@10 17 pthread_mutex_t done_lock;
nuclear@5 18 };
nuclear@5 19
nuclear@5 20 struct resman {
nuclear@11 21 struct resource **res;
nuclear@10 22 struct thread_pool *tpool;
nuclear@5 23
nuclear@5 24 resman_load_func load_func;
nuclear@10 25 resman_done_func done_func;
nuclear@5 26 resman_destroy_func destroy_func;
nuclear@5 27
nuclear@5 28 void *load_func_cls;
nuclear@10 29 void *done_func_cls;
nuclear@5 30 void *destroy_func_cls;
nuclear@5 31 };
nuclear@5 32
nuclear@5 33
nuclear@5 34 static int find_resource(struct resman *rman, const char *fname);
nuclear@5 35 static int add_resource(struct resman *rman, const char *fname, void *data);
nuclear@10 36 static void work_func(void *data, void *cls);
nuclear@5 37
nuclear@5 38 struct resman *resman_create(void)
nuclear@5 39 {
nuclear@5 40 struct resman *rman = malloc(sizeof *rman);
nuclear@5 41 if(resman_init(rman) == -1) {
nuclear@5 42 free(rman);
nuclear@5 43 return 0;
nuclear@5 44 }
nuclear@5 45 return rman;
nuclear@5 46 }
nuclear@5 47
nuclear@5 48 void resman_free(struct resman *rman)
nuclear@5 49 {
nuclear@5 50 resman_destroy(rman);
nuclear@5 51 free(rman);
nuclear@5 52 }
nuclear@5 53
nuclear@5 54 int resman_init(struct resman *rman)
nuclear@5 55 {
nuclear@5 56 memset(rman, 0, sizeof *rman);
nuclear@5 57
nuclear@10 58 if(!(rman->tpool = tpool_create(TPOOL_AUTO))) {
nuclear@10 59 return -1;
nuclear@10 60 }
nuclear@10 61 tpool_set_work_func(rman->tpool, work_func, rman);
nuclear@10 62
nuclear@5 63 if(!(rman->res = dynarr_alloc(0, sizeof *rman->res))) {
nuclear@10 64 tpool_free(rman->tpool);
nuclear@5 65 return -1;
nuclear@5 66 }
nuclear@5 67
nuclear@5 68 return 0;
nuclear@5 69 }
nuclear@5 70
nuclear@5 71 void resman_destroy(struct resman *rman)
nuclear@5 72 {
nuclear@5 73 int i;
nuclear@5 74 if(!rman) return;
nuclear@5 75
nuclear@5 76 for(i=0; i<dynarr_size(rman->res); i++) {
nuclear@5 77 if(rman->destroy_func) {
nuclear@11 78 rman->destroy_func(i, rman->destroy_func_cls);
nuclear@5 79 }
nuclear@11 80 free(rman->res[i]);
nuclear@5 81 }
nuclear@5 82 dynarr_free(rman->res);
nuclear@10 83
nuclear@10 84 tpool_free(rman->tpool);
nuclear@5 85 }
nuclear@5 86
nuclear@5 87
nuclear@5 88 void resman_set_load_func(struct resman *rman, resman_load_func func, void *cls)
nuclear@5 89 {
nuclear@5 90 rman->load_func = func;
nuclear@5 91 rman->load_func_cls = cls;
nuclear@5 92 }
nuclear@5 93
nuclear@10 94 void resman_set_done_func(struct resman *rman, resman_done_func func, void *cls)
nuclear@5 95 {
nuclear@10 96 rman->done_func = func;
nuclear@10 97 rman->done_func_cls = cls;
nuclear@5 98 }
nuclear@5 99
nuclear@5 100 void resman_set_destroy_func(struct resman *rman, resman_destroy_func func, void *cls)
nuclear@5 101 {
nuclear@5 102 rman->destroy_func = func;
nuclear@5 103 rman->destroy_func_cls = cls;
nuclear@5 104 }
nuclear@5 105
nuclear@5 106 int resman_lookup(struct resman *rman, const char *fname, void *data)
nuclear@5 107 {
nuclear@5 108 int ridx;
nuclear@5 109
nuclear@5 110 if((ridx = find_resource(rman, fname)) != -1) {
nuclear@5 111 return ridx;
nuclear@5 112 }
nuclear@5 113
nuclear@5 114 /* resource not found, create a new one and start a loading job */
nuclear@5 115 return add_resource(rman, fname, data);
nuclear@5 116 }
nuclear@5 117
nuclear@5 118 void resman_wait(struct resman *rman, int id)
nuclear@5 119 {
nuclear@5 120 /* TODO */
nuclear@5 121 }
nuclear@5 122
nuclear@5 123 int resman_poll(struct resman *rman)
nuclear@5 124 {
nuclear@10 125 int i, num_res;
nuclear@10 126
nuclear@10 127 if(!rman->done_func) {
nuclear@10 128 return 0; /* no done callback; there's no point in checking anything */
nuclear@10 129 }
nuclear@10 130
nuclear@10 131 num_res = dynarr_size(rman->res);
nuclear@10 132 for(i=0; i<num_res; i++) {
nuclear@11 133 struct resource *res = rman->res[i];
nuclear@10 134
nuclear@10 135 pthread_mutex_lock(&res->done_lock);
nuclear@10 136 if(!res->done_pending) {
nuclear@10 137 pthread_mutex_unlock(&res->done_lock);
nuclear@10 138 continue;
nuclear@10 139 }
nuclear@10 140
nuclear@10 141 /* so a done callback *is* pending... */
nuclear@10 142 res->done_pending = 0;
nuclear@11 143 rman->done_func(i, rman->done_func_cls);
nuclear@10 144 pthread_mutex_unlock(&res->done_lock);
nuclear@10 145 }
nuclear@5 146 return 0;
nuclear@5 147 }
nuclear@5 148
nuclear@11 149 const char *resman_get_res_name(struct resman *rman, int res_id)
nuclear@11 150 {
nuclear@11 151 if(res_id >= 0 && res_id < dynarr_size(rman->res)) {
nuclear@11 152 return rman->res[res_id]->name;
nuclear@11 153 }
nuclear@11 154 return 0;
nuclear@11 155 }
nuclear@5 156
nuclear@5 157 void resman_set_res_data(struct resman *rman, int res_id, void *data)
nuclear@5 158 {
nuclear@5 159 if(res_id >= 0 && res_id < dynarr_size(rman->res)) {
nuclear@11 160 rman->res[res_id]->data = data;
nuclear@5 161 }
nuclear@5 162 }
nuclear@5 163
nuclear@5 164 void *resman_get_res_data(struct resman *rman, int res_id)
nuclear@5 165 {
nuclear@5 166 if(res_id >= 0 && res_id < dynarr_size(rman->res)) {
nuclear@11 167 return rman->res[res_id]->data;
nuclear@5 168 }
nuclear@5 169 return 0;
nuclear@5 170 }
nuclear@5 171
nuclear@11 172 int resman_get_res_result(struct resman *rman, int res_id)
nuclear@10 173 {
nuclear@10 174 if(res_id >= 0 && res_id < dynarr_size(rman->res)) {
nuclear@11 175 return rman->res[res_id]->result;
nuclear@10 176 }
nuclear@10 177 return -1;
nuclear@10 178 }
nuclear@10 179
nuclear@5 180 static int find_resource(struct resman *rman, const char *fname)
nuclear@5 181 {
nuclear@5 182 int i, sz = dynarr_size(rman->res);
nuclear@5 183
nuclear@5 184 for(i=0; i<sz; i++) {
nuclear@11 185 if(strcmp(rman->res[i]->name, fname) == 0) {
nuclear@5 186 return i;
nuclear@5 187 }
nuclear@5 188 }
nuclear@5 189 return -1;
nuclear@5 190 }
nuclear@5 191
nuclear@5 192 static int add_resource(struct resman *rman, const char *fname, void *data)
nuclear@5 193 {
nuclear@5 194 int idx = dynarr_size(rman->res);
nuclear@11 195 struct resource *res;
nuclear@11 196 struct resource **tmparr;
nuclear@5 197
nuclear@11 198 if(!(res = malloc(sizeof *res))) {
nuclear@5 199 return -1;
nuclear@5 200 }
nuclear@11 201 res->id = idx;
nuclear@11 202 res->name = strdup(fname);
nuclear@11 203 assert(res->name);
nuclear@11 204 res->data = data;
nuclear@5 205
nuclear@11 206 if(!(tmparr = dynarr_push(rman->res, &res))) {
nuclear@11 207 free(res);
nuclear@11 208 return -1;
nuclear@11 209 }
nuclear@11 210 rman->res = tmparr;
nuclear@5 211
nuclear@10 212 /* start a loading job ... */
nuclear@11 213 tpool_add_work(rman->tpool, rman->res[idx]);
nuclear@5 214 return idx;
nuclear@5 215 }
nuclear@10 216
nuclear@10 217 /* this is the background work function which handles all the
nuclear@10 218 * first-stage resource loading...
nuclear@10 219 */
nuclear@10 220 static void work_func(void *data, void *cls)
nuclear@10 221 {
nuclear@10 222 struct resource *res = data;
nuclear@10 223 struct resman *rman = cls;
nuclear@10 224
nuclear@11 225 res->result = rman->load_func(res->name, res->id, rman->load_func_cls);
nuclear@10 226 pthread_mutex_lock(&res->done_lock);
nuclear@10 227 res->done_pending = 1;
nuclear@10 228 pthread_mutex_unlock(&res->done_lock);
nuclear@10 229 }