libresman
changeset 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 0a789208498d |
files | examples/imgthumbs/src/thumbs.c examples/imgthumbs/src/thumbs.h src/resman.c |
diffstat | 3 files changed, 93 insertions(+), 20 deletions(-) [+] |
line diff
1.1 --- a/examples/imgthumbs/src/thumbs.c Sat Feb 08 04:21:08 2014 +0200 1.2 +++ b/examples/imgthumbs/src/thumbs.c Sat Feb 08 07:41:39 2014 +0200 1.3 @@ -24,7 +24,8 @@ 1.4 { 1.5 DIR *dir; 1.6 struct dirent *dent; 1.7 - struct thumbnail *list = 0; 1.8 + /* allocate dummy head node */ 1.9 + struct thumbnail *list = calloc(1, sizeof *list); 1.10 1.11 /*unsigned int intfmt = GL_COMPRESSED_RGB; 1.12 if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { 1.13 @@ -85,8 +86,8 @@ 1.14 img_free_pixels(pixels); 1.15 */ 1.16 1.17 - node->next = list; 1.18 - list = node; 1.19 + node->next = list->next; 1.20 + node->prev = list; 1.21 } 1.22 closedir(dir); 1.23 1.24 @@ -130,6 +131,7 @@ 1.25 1.26 glMatrixMode(GL_MODELVIEW); 1.27 1.28 + thumbs = thumbs->next; /* skip dummy node */ 1.29 while(thumbs) { 1.30 glPushMatrix(); 1.31 glTranslatef(x, y, 0); 1.32 @@ -204,6 +206,7 @@ 1.33 1.34 if(img_load(rdata->img, fname) == -1) { 1.35 img_free(rdata->img); 1.36 + rdata->img = 0; 1.37 return -1; 1.38 } 1.39 rdata->aspect = (float)rdata->img->width / (float)rdata->img->height; 1.40 @@ -216,9 +219,16 @@ 1.41 1.42 static int done_res_texture(int id, void *cls) 1.43 { 1.44 - struct thumbnail *rdata; 1.45 + struct thumbnail *rdata = resman_get_res_data(texman, id); 1.46 + int load_result = resman_get_res_result(texman, id); 1.47 1.48 - rdata = resman_get_res_data(texman, id); 1.49 + if(load_result == -1) { 1.50 + /* returning -1 will remove this resource, the free_res_texture 1.51 + * destroy handler will be called, which will remove the node 1.52 + * from the list 1.53 + */ 1.54 + return -1; 1.55 + } 1.56 1.57 if(resman_get_res_result(texman, id) != 0 || !rdata) { 1.58 fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id)); 1.59 @@ -240,14 +250,23 @@ 1.60 1.61 static void free_res_texture(int id, void *cls) 1.62 { 1.63 - struct thumbnail *rdata = resman_get_res_data(texman, id); 1.64 + struct thumbnail *thumb = resman_get_res_data(texman, id); 1.65 1.66 - if(rdata) { 1.67 - if(rdata->tex) { 1.68 - glDeleteTextures(1, &rdata->tex); 1.69 + if(thumb) { 1.70 + if(thumb->tex) { 1.71 + glDeleteTextures(1, &thumb->tex); 1.72 } 1.73 - if(rdata->img) { 1.74 - img_free(rdata->img); 1.75 + if(thumb->img) { 1.76 + img_free(thumb->img); 1.77 } 1.78 } 1.79 + 1.80 + /* remove from the list */ 1.81 + if(thumb->prev) { 1.82 + thumb->prev->next = thumb->next; 1.83 + } 1.84 + if(thumb->next) { 1.85 + thumb->next->prev = thumb->prev; 1.86 + } 1.87 + free(thumb); 1.88 }
2.1 --- a/examples/imgthumbs/src/thumbs.h Sat Feb 08 04:21:08 2014 +0200 2.2 +++ b/examples/imgthumbs/src/thumbs.h Sat Feb 08 07:41:39 2014 +0200 2.3 @@ -13,7 +13,7 @@ 2.4 2.5 struct img_pixmap *img; 2.6 2.7 - struct thumbnail *next; 2.8 + struct thumbnail *next, *prev; 2.9 }; 2.10 2.11 struct thumbnail *create_thumbs(const char *dirpath);
3.1 --- a/src/resman.c Sat Feb 08 04:21:08 2014 +0200 3.2 +++ b/src/resman.c Sat Feb 08 07:41:39 2014 +0200 3.3 @@ -21,6 +21,8 @@ 3.4 struct resource **res; 3.5 struct thread_pool *tpool; 3.6 3.7 + pthread_mutex_t lock; /* global resman lock (for res array changes) */ 3.8 + 3.9 resman_load_func load_func; 3.10 resman_done_func done_func; 3.11 resman_destroy_func destroy_func; 3.12 @@ -33,6 +35,7 @@ 3.13 3.14 static int find_resource(struct resman *rman, const char *fname); 3.15 static int add_resource(struct resman *rman, const char *fname, void *data); 3.16 +static void remove_resource(struct resman *rman, int idx); 3.17 static void work_func(void *data, void *cls); 3.18 3.19 struct resman *resman_create(void) 3.20 @@ -65,6 +68,8 @@ 3.21 return -1; 3.22 } 3.23 3.24 + pthread_mutex_init(&rman->lock, 0); 3.25 + 3.26 return 0; 3.27 } 3.28 3.29 @@ -82,6 +87,8 @@ 3.30 dynarr_free(rman->res); 3.31 3.32 tpool_free(rman->tpool); 3.33 + 3.34 + pthread_mutex_destroy(&rman->lock); 3.35 } 3.36 3.37 3.38 @@ -131,6 +138,9 @@ 3.39 num_res = dynarr_size(rman->res); 3.40 for(i=0; i<num_res; i++) { 3.41 struct resource *res = rman->res[i]; 3.42 + if(!res) { 3.43 + continue; 3.44 + } 3.45 3.46 printf("locking mutex %d\n", res->id); 3.47 pthread_mutex_lock(&res->done_lock); 3.48 @@ -142,7 +152,13 @@ 3.49 3.50 /* so a done callback *is* pending... */ 3.51 res->done_pending = 0; 3.52 - rman->done_func(i, rman->done_func_cls); 3.53 + if(rman->done_func(i, rman->done_func_cls) == -1) { 3.54 + /* done-func returned -1, so let's remove the resource */ 3.55 + printf(" unlocking mutex %d\n", res->id); 3.56 + pthread_mutex_unlock(&res->done_lock); 3.57 + remove_resource(rman, i); 3.58 + continue; 3.59 + } 3.60 printf(" unlocking mutex %d\n", res->id); 3.61 pthread_mutex_unlock(&res->done_lock); 3.62 } 3.63 @@ -194,31 +210,64 @@ 3.64 3.65 static int add_resource(struct resman *rman, const char *fname, void *data) 3.66 { 3.67 - int idx = dynarr_size(rman->res); 3.68 + int i, idx = -1, size = dynarr_size(rman->res); 3.69 struct resource *res; 3.70 struct resource **tmparr; 3.71 3.72 + /* allocate a new resource */ 3.73 if(!(res = malloc(sizeof *res))) { 3.74 return -1; 3.75 } 3.76 - res->id = idx; 3.77 + memset(res, 0, sizeof *res); 3.78 + 3.79 res->name = strdup(fname); 3.80 assert(res->name); 3.81 res->data = data; 3.82 - 3.83 pthread_mutex_init(&res->done_lock, 0); 3.84 3.85 - if(!(tmparr = dynarr_push(rman->res, &res))) { 3.86 - free(res); 3.87 - return -1; 3.88 + 3.89 + /* check to see if there's an emtpy (previously erased) slot */ 3.90 + for(i=0; i<size; i++) { 3.91 + if(!rman->res[i]) { 3.92 + idx = i; 3.93 + break; 3.94 + } 3.95 } 3.96 - rman->res = tmparr; 3.97 + 3.98 + if(idx == -1) { 3.99 + /* free slot not found, append a new one */ 3.100 + idx = size; 3.101 + 3.102 + if(!(tmparr = dynarr_push(rman->res, &res))) { 3.103 + free(res); 3.104 + return -1; 3.105 + } 3.106 + rman->res = tmparr; 3.107 + } else { 3.108 + /* free slot found, just use it */ 3.109 + res = rman->res[idx]; 3.110 + } 3.111 + 3.112 + res->id = idx; /* set the resource id */ 3.113 3.114 /* start a loading job ... */ 3.115 tpool_add_work(rman->tpool, rman->res[idx]); 3.116 return idx; 3.117 } 3.118 3.119 +/* remove a resource and leave the pointer null to reuse the slot */ 3.120 +static void remove_resource(struct resman *rman, int idx) 3.121 +{ 3.122 + if(rman->destroy_func) { 3.123 + rman->destroy_func(idx, rman->destroy_func_cls); 3.124 + } 3.125 + 3.126 + pthread_mutex_destroy(&rman->res[idx]->done_lock); 3.127 + 3.128 + free(rman->res[idx]); 3.129 + rman->res[idx] = 0; 3.130 +} 3.131 + 3.132 /* this is the background work function which handles all the 3.133 * first-stage resource loading... 3.134 */ 3.135 @@ -228,6 +277,11 @@ 3.136 struct resman *rman = cls; 3.137 3.138 res->result = rman->load_func(res->name, res->id, rman->load_func_cls); 3.139 + if(res->result == -1 && !rman->done_func) { 3.140 + /* if there's no done function and we got an error, remove the resource now */ 3.141 + remove_resource(rman, res->id); 3.142 + return; 3.143 + } 3.144 3.145 printf("locking mutex %d\n", res->id); 3.146 pthread_mutex_lock(&res->done_lock);