# HG changeset patch # User John Tsiombikas # Date 1391838099 -7200 # Node ID a42888d26839d867473908f49dac6a3da0eff435 # Parent 84f55eab27cb3fd8c854e37db6ae101e84c25dae bit more progress... diff -r 84f55eab27cb -r a42888d26839 examples/imgthumbs/src/thumbs.c --- a/examples/imgthumbs/src/thumbs.c Sat Feb 08 04:21:08 2014 +0200 +++ b/examples/imgthumbs/src/thumbs.c Sat Feb 08 07:41:39 2014 +0200 @@ -24,7 +24,8 @@ { DIR *dir; struct dirent *dent; - struct thumbnail *list = 0; + /* allocate dummy head node */ + struct thumbnail *list = calloc(1, sizeof *list); /*unsigned int intfmt = GL_COMPRESSED_RGB; if(!strstr((char*)glGetString(GL_EXTENSIONS), "GL_ARB_texture_compression")) { @@ -85,8 +86,8 @@ img_free_pixels(pixels); */ - node->next = list; - list = node; + node->next = list->next; + node->prev = list; } closedir(dir); @@ -130,6 +131,7 @@ glMatrixMode(GL_MODELVIEW); + thumbs = thumbs->next; /* skip dummy node */ while(thumbs) { glPushMatrix(); glTranslatef(x, y, 0); @@ -204,6 +206,7 @@ if(img_load(rdata->img, fname) == -1) { img_free(rdata->img); + rdata->img = 0; return -1; } rdata->aspect = (float)rdata->img->width / (float)rdata->img->height; @@ -216,9 +219,16 @@ static int done_res_texture(int id, void *cls) { - struct thumbnail *rdata; + struct thumbnail *rdata = resman_get_res_data(texman, id); + int load_result = resman_get_res_result(texman, id); - rdata = resman_get_res_data(texman, id); + if(load_result == -1) { + /* returning -1 will remove this resource, the free_res_texture + * destroy handler will be called, which will remove the node + * from the list + */ + return -1; + } if(resman_get_res_result(texman, id) != 0 || !rdata) { fprintf(stderr, "failed to load resource %d (%s)\n", id, resman_get_res_name(texman, id)); @@ -240,14 +250,23 @@ static void free_res_texture(int id, void *cls) { - struct thumbnail *rdata = resman_get_res_data(texman, id); + struct thumbnail *thumb = resman_get_res_data(texman, id); - if(rdata) { - if(rdata->tex) { - glDeleteTextures(1, &rdata->tex); + if(thumb) { + if(thumb->tex) { + glDeleteTextures(1, &thumb->tex); } - if(rdata->img) { - img_free(rdata->img); + if(thumb->img) { + img_free(thumb->img); } } + + /* remove from the list */ + if(thumb->prev) { + thumb->prev->next = thumb->next; + } + if(thumb->next) { + thumb->next->prev = thumb->prev; + } + free(thumb); } diff -r 84f55eab27cb -r a42888d26839 examples/imgthumbs/src/thumbs.h --- a/examples/imgthumbs/src/thumbs.h Sat Feb 08 04:21:08 2014 +0200 +++ b/examples/imgthumbs/src/thumbs.h Sat Feb 08 07:41:39 2014 +0200 @@ -13,7 +13,7 @@ struct img_pixmap *img; - struct thumbnail *next; + struct thumbnail *next, *prev; }; struct thumbnail *create_thumbs(const char *dirpath); diff -r 84f55eab27cb -r a42888d26839 src/resman.c --- a/src/resman.c Sat Feb 08 04:21:08 2014 +0200 +++ b/src/resman.c Sat Feb 08 07:41:39 2014 +0200 @@ -21,6 +21,8 @@ struct resource **res; struct thread_pool *tpool; + pthread_mutex_t lock; /* global resman lock (for res array changes) */ + resman_load_func load_func; resman_done_func done_func; resman_destroy_func destroy_func; @@ -33,6 +35,7 @@ static int find_resource(struct resman *rman, const char *fname); static int add_resource(struct resman *rman, const char *fname, void *data); +static void remove_resource(struct resman *rman, int idx); static void work_func(void *data, void *cls); struct resman *resman_create(void) @@ -65,6 +68,8 @@ return -1; } + pthread_mutex_init(&rman->lock, 0); + return 0; } @@ -82,6 +87,8 @@ dynarr_free(rman->res); tpool_free(rman->tpool); + + pthread_mutex_destroy(&rman->lock); } @@ -131,6 +138,9 @@ num_res = dynarr_size(rman->res); for(i=0; ires[i]; + if(!res) { + continue; + } printf("locking mutex %d\n", res->id); pthread_mutex_lock(&res->done_lock); @@ -142,7 +152,13 @@ /* so a done callback *is* pending... */ res->done_pending = 0; - rman->done_func(i, rman->done_func_cls); + if(rman->done_func(i, rman->done_func_cls) == -1) { + /* done-func returned -1, so let's remove the resource */ + printf(" unlocking mutex %d\n", res->id); + pthread_mutex_unlock(&res->done_lock); + remove_resource(rman, i); + continue; + } printf(" unlocking mutex %d\n", res->id); pthread_mutex_unlock(&res->done_lock); } @@ -194,31 +210,64 @@ static int add_resource(struct resman *rman, const char *fname, void *data) { - int idx = dynarr_size(rman->res); + int i, idx = -1, size = dynarr_size(rman->res); struct resource *res; struct resource **tmparr; + /* allocate a new resource */ if(!(res = malloc(sizeof *res))) { return -1; } - res->id = idx; + memset(res, 0, sizeof *res); + res->name = strdup(fname); assert(res->name); res->data = data; - pthread_mutex_init(&res->done_lock, 0); - if(!(tmparr = dynarr_push(rman->res, &res))) { - free(res); - return -1; + + /* check to see if there's an emtpy (previously erased) slot */ + for(i=0; ires[i]) { + idx = i; + break; + } } - rman->res = tmparr; + + if(idx == -1) { + /* free slot not found, append a new one */ + idx = size; + + if(!(tmparr = dynarr_push(rman->res, &res))) { + free(res); + return -1; + } + rman->res = tmparr; + } else { + /* free slot found, just use it */ + res = rman->res[idx]; + } + + res->id = idx; /* set the resource id */ /* start a loading job ... */ tpool_add_work(rman->tpool, rman->res[idx]); return idx; } +/* remove a resource and leave the pointer null to reuse the slot */ +static void remove_resource(struct resman *rman, int idx) +{ + if(rman->destroy_func) { + rman->destroy_func(idx, rman->destroy_func_cls); + } + + pthread_mutex_destroy(&rman->res[idx]->done_lock); + + free(rman->res[idx]); + rman->res[idx] = 0; +} + /* this is the background work function which handles all the * first-stage resource loading... */ @@ -228,6 +277,11 @@ struct resman *rman = cls; res->result = rman->load_func(res->name, res->id, rman->load_func_cls); + if(res->result == -1 && !rman->done_func) { + /* if there's no done function and we got an error, remove the resource now */ + remove_resource(rman, res->id); + return; + } printf("locking mutex %d\n", res->id); pthread_mutex_lock(&res->done_lock);