Mercurial > hg > dmlib
diff dmres.c @ 359:59045853853d
Make resource management re-entrant.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 16 Oct 2012 21:25:46 +0300 |
parents | 6d9d43bb68eb |
children | a0160ffdf7e5 |
line wrap: on
line diff
--- a/dmres.c Tue Oct 16 21:24:48 2012 +0300 +++ b/dmres.c Tue Oct 16 21:25:46 2012 +0300 @@ -8,31 +8,13 @@ #include <time.h> -#define DMRES_LOCK(x) dmMutexLock(dfResourcesMutex) -#define DMRES_UNLOCK(x) dmMutexUnlock(dfResourcesMutex) - - -/* Global variables - */ -static BOOL dfResInitialized = FALSE; -static int dfResFlags = 0; -static char * dfResPath = NULL; -DMResource * dfResources = NULL; -DMMutex * dfResourcesMutex = NULL; - - -#ifdef DM_USE_PACKFS -static DMPackFile *dfResPackFile = NULL; -static char * dfResPackFilename = NULL; -#endif - - -DMResource *dmres_new(const char *filename, int flags, size_t size) +DMResource *dmres_new(DMResourceLib *lib, const char *filename, int flags, size_t size) { DMResource *node = dmMalloc0(sizeof(DMResource)); if (node == NULL) return NULL; + node->lib = lib; node->filename = dm_strdup(filename); node->flags = flags; node->dataSize = size; @@ -84,44 +66,55 @@ } -static void dmres_insert(DMResource * node) +void dmres_insert(DMResourceLib *lib, DMResource * node) { - if (dfResources != NULL) + if (lib == NULL) + return; + + node->lib = lib; + + if (lib->resources != NULL) { - node->prev = dfResources->prev; - dfResources->prev->next = node; - dfResources->prev = node; + node->prev = lib->resources->prev; + lib->resources->prev->next = node; + lib->resources->prev = node; } else { - dfResources = node->prev = node; + lib->resources = node->prev = node; } node->next = NULL; } -static void dmres_delete(DMResource * node) +void dmres_delete(DMResourceLib *lib, DMResource * node) { + if (lib == NULL) + return; + if (node->prev) node->prev->next = node->next; if (node->next) node->next->prev = node->prev; else - dfResources->prev = node->prev; + lib->resources->prev = node->prev; node->prev = node->next = NULL; } -DMResource * dmres_find(const char *filename) +DMResource * dmres_find(DMResourceLib *lib, const char *filename) { DMResource *node, *found = NULL; - DMRES_LOCK(); + if (lib == NULL) + return NULL; - for (node = dfResources; node != NULL; node = node->next) + dmMutexLock(lib->mutex); + + for (node = lib->resources; node != NULL; node = node->next) { if (strcmp(node->filename, filename) == 0) { @@ -130,7 +123,7 @@ } } - DMRES_UNLOCK(); + dmMutexUnlock(lib->mutex); return found; } @@ -322,8 +315,11 @@ z_stream cstream; Uint8 * cbuffer = NULL; + if (handle->lib == NULL || handle->lib->packFile == NULL) + return DMERR_NULLPTR; + // Search PACK nodelist for file - if ((node = dm_pack_find(dfResPackFile->entries, handle->filename)) == NULL) + if ((node = dm_pack_find(handle->lib->packFile->entries, handle->filename)) == NULL) { dmError("Entry '%s' not found in PACK file.\n", handle->filename); res = DMERR_NOT_FOUND; @@ -331,7 +327,7 @@ } // Seek to entry - if (fseek(dfResPackFile->file, node->offset, SEEK_SET) == -1) + if (fseek(handle->lib->packFile->file, node->offset, SEEK_SET) == -1) { dmError("Could not seek node position in PACK file.\n"); res = DMERR_FSEEK; @@ -378,7 +374,7 @@ cstream.avail_in = fread( cbuffer, sizeof(Uint8), (cdataLeft >= DPACK_TMPSIZE) ? DPACK_TMPSIZE : cdataLeft, - dfResPackFile->file); + handle->lib->packFile->file); cdataLeft -= cstream.avail_in; cstream.next_in = cbuffer; @@ -540,7 +536,7 @@ if (handle->fops == NULL) { #ifdef DM_USE_PACKFS - if (dfResFlags & DRF_USE_PACK) + if (handle->lib->flags & DRF_USE_PACK) handle->fops = &dfPackFileOps; #ifdef DM_USE_STDIO else @@ -562,7 +558,7 @@ // Check if we want to preload raw data? if (((handle->flags & DMF_PRELOAD_RAW) || - (dfResFlags & DRF_PRELOAD_ALL)) && + (handle->lib->flags & DRF_PRELOAD_ALL)) && (handle->flags & DMF_LOADED_RAW) == 0 && handle->fops->preload != NULL) { @@ -588,7 +584,7 @@ } // Check if resource data is to be preloaded - if (((handle->flags & DMF_PRELOAD_RES) || (dfResFlags & DRF_PRELOAD_RES)) && + if (((handle->flags & DMF_PRELOAD_RES) || (handle->lib->flags & DRF_PRELOAD_RES)) && (handle->flags & DMF_LOADED_RES) == 0 && handle->rops != NULL && handle->rops->load != NULL) @@ -609,22 +605,22 @@ } -DMResource *dmf_open(const char *filename) +DMResource *dmf_open(DMResourceLib *lib, const char *filename) { int ret; DMResource *handle; // Check master directory for resource - if ((handle = dmres_find(filename)) == NULL) + if ((handle = dmres_find(lib, filename)) == NULL) { #ifdef DM_USE_STDIO // Hmm.. does not exist? Fall back to a stdio file - handle = dmres_new(filename, 0, 0); + handle = dmres_new(lib, filename, 0, 0); if (handle == NULL) return NULL; handle->fops = &dfStdioFileOps; - dmres_insert(handle); + dmres_insert(lib, handle); #else // Stdio not enabled, fail return NULL; @@ -654,21 +650,21 @@ } -DMResource * dmf_open_memio(const char *filename, Uint8 *buf, size_t len) +DMResource * dmf_create_memio(DMResourceLib *lib, const char *filename, Uint8 *buf, size_t len) { DMResource *handle; // Check master directory for resource - if ((handle = dmres_find(filename)) == NULL) + if ((handle = dmres_find(lib, filename)) == NULL) { // Hmm.. does not exist? Fall back to a stdio file - handle = dmres_new(filename, DMF_LOADED_RAW, len); + handle = dmres_new(lib, filename, DMF_LOADED_RAW, len); if (handle == NULL) return NULL; handle->fops = &dfMemIOFileOps; handle->data = buf; - dmres_insert(handle); + dmres_insert(lib, handle); } // Increase refcount @@ -681,7 +677,7 @@ #ifdef DM_USE_STDIO DMResource * dmf_create_stdio(const char *filename, const char *mode) { - DMResource *handle = dmres_new(filename, 0, 0); + DMResource *handle = dmres_new(NULL, filename, 0, 0); if (handle == NULL) return NULL; @@ -705,7 +701,7 @@ DMResource * dmf_create_stdio_stream(FILE *fh) { - DMResource *handle = dmres_new("", 0, 0); + DMResource *handle = dmres_new(NULL, "", 0, 0); if (handle == NULL) return NULL; @@ -803,13 +799,12 @@ } - int dmres_ref(DMResource *node) { - DMRES_LOCK(); + if (node->lib != NULL) dmMutexLock(node->lib->mutex); node->atime = time(NULL); node->refcount++; - DMRES_UNLOCK(); + if (node->lib != NULL) dmMutexUnlock(node->lib->mutex); return node->refcount; } @@ -817,9 +812,9 @@ int dmres_unref(DMResource *node) { - DMRES_LOCK(); + if (node->lib != NULL) dmMutexLock(node->lib->mutex); node->refcount--; - DMRES_UNLOCK(); + if (node->lib != NULL) dmMutexUnlock(node->lib->mutex); return node->refcount; } @@ -861,7 +856,7 @@ } -int dmres_load_resfile(const char *filename) +int dmres_load_resfile(DMResourceLib *lib, const char *filename) { int ret = DMERR_OK; char line[256]; @@ -869,7 +864,7 @@ if (f == NULL) return DMERR_FOPEN; - DMRES_LOCK(); + dmMutexLock(lib->mutex); while (fgets(line, sizeof(line) - 1, f) != NULL) { @@ -883,23 +878,17 @@ line[i] = 0; for (i = fsep; isspace(line[i]); i++); - - if (sscanf(&line[i], "%x", &flags) == 1 && - strlen(&line[fnstart]) > 0) - { - - } } } - DMRES_UNLOCK(); + dmMutexUnlock(lib->mutex); fclose(f); return ret; } -int dmres_write_resfile(const char *filename) +int dmres_write_resfile(DMResourceLib *lib, const char *filename) { int ret; DMResource *node; @@ -907,11 +896,13 @@ if (f == NULL) return DMERR_FOPEN; - DMRES_LOCK(); + dmMutexLock(lib->mutex); - for (node = dfResources; node != NULL; node = node->next) + for (node = lib->resources; node != NULL; node = node->next) { - if (fprintf(f, "%s|%08x\n", node->filename, node->flags) < 0) + char tmp[64]; + dmres_flags_to_symbolic(tmp, sizeof(tmp), node->flags); + if (fprintf(f, "%s|%s\n", node->filename, tmp) < 0) { ret = DMERR_FWRITE; goto error; @@ -919,7 +910,7 @@ } error: - DMRES_UNLOCK(); + dmMutexUnlock(lib->mutex); fclose(f); return ret; } @@ -927,15 +918,18 @@ /* Resources subsystem initialization and shutdown routines */ -int dmres_init(const char *filename, const char *path, const int flags, int (*classifier)(DMResource *)) +int dmres_init(DMResourceLib **plib, const char *filename, const char *path, const int flags, int (*classifier)(DMResource *)) { - // Check if we are already initialized - if (dfResInitialized) - return DMERR_ALREADY_INIT; + DMResourceLib *lib; + + // Allocate the resource library structure + if ((*plib = lib = dmMalloc0(sizeof(DMResourceLib))) == NULL) + return DMERR_MALLOC; - dfResFlags = flags; - dfResPath = dm_strdup((path != NULL) ? path : DMRES_DATA_PATH); - dfResourcesMutex = dmCreateMutex(); + // Basic data + lib->mutex = dmCreateMutex(); + lib->flags = flags; + lib->resPath = dm_strdup((path != NULL) ? path : DMRES_DATA_PATH); if (flags & DRF_USE_PACK) @@ -944,22 +938,22 @@ int ret; DMPackEntry *node; - dfResPackFilename = dm_strdup((filename != NULL) ? filename : DMRES_DATA_PACK); + lib->packFilename = dm_strdup((filename != NULL) ? filename : DMRES_DATA_PACK); // Initialize PACK, open as read-only - ret = dm_pack_open(dfResPackFilename, &dfResPackFile, TRUE); + ret = dm_pack_open(lib->packFilename, &lib->packFile, TRUE); if (ret != DMERR_OK) { dmError("Error opening PACK file '%s', #%i: %s\n", - dfResPackFilename, ret, dmErrorStr(ret)); + lib->packFilename, ret, dmErrorStr(ret)); return DMERR_INIT_FAIL; } // Initialize resources from a PACK file - for (node = dfResPackFile->entries; node != NULL; node = node->next) + for (node = lib->packFile->entries; node != NULL; node = node->next) { - DMResource *res = dmres_new(node->filename, node->resFlags & DMF_MASK, node->size); + DMResource *res = dmres_new(lib, node->filename, node->resFlags & DMF_MASK, node->size); if (res == NULL) { dmError("Could not allocate memory for resource node '%s' [0x%08x], %d.\n", @@ -967,7 +961,7 @@ return DMERR_INIT_FAIL; } - dmres_insert(res); + dmres_insert(lib, res); } #else @@ -978,8 +972,8 @@ else { // Initialize resources from a resource directory - char *resFilename = dm_strdup_printf("%s%s", dfResPath, DMRES_RES_FILE); - int ret = dmres_load_resfile(resFilename); + char *resFilename = dm_strdup_printf("%s%s", lib->resPath, DMRES_RES_FILE); + int ret = dmres_load_resfile(lib, resFilename); dmFree(resFilename); if (ret != DMERR_OK) @@ -987,10 +981,10 @@ } // Okay, classify resources - if (dfResources != NULL && classifier != NULL) + if (lib->resources != NULL && classifier != NULL) { DMResource *node; - for (node = dfResources; node != NULL; node = node->next) + for (node = lib->resources; node != NULL; node = node->next) { int ret = classifier(node); if (ret != DMERR_OK) @@ -999,36 +993,36 @@ } // Initialization complete - dfResInitialized = TRUE; return DMERR_OK; } -void dmres_close(void) +int dmres_close(DMResourceLib *lib) { DMResource *node; - DMRES_LOCK(); + + if (lib == NULL) + return DMERR_NULLPTR; + + dmMutexLock(lib->mutex); - if (!dfResInitialized) - return; - // Shutdown possible subsystems #ifdef DM_USE_PACKFS - if (dfResFlags & DRF_USE_PACK) + if (lib->flags & DRF_USE_PACK) { - int res = dm_pack_close(dfResPackFile); + int res = dm_pack_close(lib->packFile); if (res != DMERR_OK) { dmError("Error closing PACK, #%i: %s\n", res, dmErrorStr(res)); } - dmFree(dfResPackFilename); + dmFree(lib->packFilename); } #endif // Free resource entries - node = dfResources; + node = lib->resources; while (node != NULL) { DMResource *next = node->next; @@ -1037,65 +1031,64 @@ } // Etc. - dmFree(dfResPath); - DMRES_UNLOCK(); - dmDestroyMutex(dfResourcesMutex); - dfResInitialized = FALSE; + dmFree(lib->resPath); + dmMutexUnlock(lib->mutex); + dmDestroyMutex(lib->mutex); + return DMERR_OK; } -int dmres_preload(BOOL start, int *loaded, int *total) +int dmres_preload(DMResourceLib *lib, BOOL start, int *loaded, int *total) { - static DMResource *dfPreload = NULL; int ret = DMERR_OK; - DMRES_LOCK(); + dmMutexLock(lib->mutex); // Initialize preloading - if (dfPreload == NULL || start) + if (lib->preload == NULL || start) { DMResource *node; - dfPreload = dfResources; + lib->preload = lib->resources; *loaded = 0; *total = 0; // Calculate total number of resources to be preloaded - for (node = dfResources; node != NULL; node = node->next) + for (node = lib->resources; node != NULL; node = node->next) { - if ((dfResFlags & (DRF_PRELOAD_ALL | DRF_PRELOAD_RES)) || + if ((lib->flags & (DRF_PRELOAD_ALL | DRF_PRELOAD_RES)) || (node->flags & (DMF_PRELOAD_RAW | DMF_PRELOAD_RES))) (*total)++; } } else - if (dfPreload != NULL) + if (lib->preload != NULL) { // Initialize fops and preload - dmf_init_fops(dfPreload); - if ((ret = dmf_preload(dfPreload)) != DMERR_OK) + dmf_init_fops(lib->preload); + if ((ret = dmf_preload(lib->preload)) != DMERR_OK) goto error; (*loaded)++; - dfPreload = dfPreload->next; + lib->preload = lib->preload->next; } - DMRES_UNLOCK(); - return (dfPreload == NULL) ? DMERR_OK : DMERR_PROGRESS; + dmMutexUnlock(lib->mutex); + return (lib->preload == NULL) ? DMERR_OK : DMERR_PROGRESS; error: - DMRES_UNLOCK(); + dmMutexUnlock(lib->mutex); return ret; } -void dmres_prune(int agems, int flags) +void dmres_prune(DMResourceLib *lib, int agems, int flags) { DMResource *node; int currtime = time(NULL); - DMRES_LOCK(); + dmMutexLock(lib->mutex); - for (node = dfResources; node != NULL; node = node->next) + for (node = lib->resources; node != NULL; node = node->next) { // Check if node has refcount of 0 and is // not marked as persistent resource @@ -1115,7 +1108,7 @@ } } - DMRES_UNLOCK(); + dmMutexUnlock(lib->mutex); }