diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/ers.c | 60 |
1 files changed, 29 insertions, 31 deletions
diff --git a/src/common/ers.c b/src/common/ers.c index 250e394e1..3e759c772 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -57,7 +57,7 @@ struct ers_list struct ers_list *Next; }; -typedef struct +typedef struct ers_cache { // Allocated object size, including ers_list size unsigned int ObjectSize; @@ -65,9 +65,6 @@ typedef struct // Number of ers_instances referencing this int ReferenceCount; - // Our index in the ERS_Root array - unsigned int Index; - // Reuse linked list struct ers_list *ReuseList; @@ -82,6 +79,9 @@ typedef struct // Used objects count unsigned int Used; + + // Linked list + struct ers_cache *Next, *Prev; } ers_cache_t; typedef struct @@ -104,16 +104,15 @@ typedef struct // Array containing a pointer for all ers_cache structures -static ers_cache_t *ERS_Root[ERS_ROOT_SIZE]; +static ers_cache_t *CacheList; static ers_cache_t *ers_find_cache(unsigned int size) { - int i; ers_cache_t *cache; - for (i = 0; i < ERS_ROOT_SIZE; i++) - if (ERS_Root[i] != NULL && ERS_Root[i]->ObjectSize == size) - return ERS_Root[i]; + for (cache = CacheList; cache; cache = cache->Next) + if (cache->ObjectSize == size) + return cache; CREATE(cache, ers_cache_t, 1); cache->ObjectSize = size; @@ -123,35 +122,35 @@ static ers_cache_t *ers_find_cache(unsigned int size) cache->Free = 0; cache->Used = 0; cache->Max = 0; - - for (i = 0; i < ERS_ROOT_SIZE; i++) + + if (CacheList == NULL) { - if (ERS_Root[i] == NULL) - { - ERS_Root[i] = cache; - cache->Index = i; - break; - } + CacheList = cache; } - - if (i >= ERS_ROOT_SIZE) + else { - ShowFatalError("ers_new: too many root objects, increase ERS_ROOT_SIZE.\n" - "exiting the program...\n"); - exit(EXIT_FAILURE); + CacheList->Next = cache; + cache->Prev = CacheList; } return cache; } -static void ers_free_cache(ers_cache_t *cache) +static void ers_free_cache(ers_cache_t *cache, bool remove) { unsigned int i; for (i = 0; i < cache->Used; i++) aFree(cache->Blocks[i]); - - ERS_Root[cache->Index] = NULL; + + if (cache->Prev) + cache->Prev->Next = cache->Next; + + if (cache->Next) + cache->Next->Prev = cache->Prev; + + if (CacheList == cache) + CacheList = cache->Next; aFree(cache->Blocks); aFree(cache); @@ -247,7 +246,7 @@ static void ers_obj_destroy(ERS self) ShowWarning("Memory leak detected at ERS '%s', %d objects not freed.\n", instance->Name, instance->Count); if (--instance->Cache->ReferenceCount <= 0) - ers_free_cache(instance->Cache); + ers_free_cache(instance->Cache, true); aFree(instance); } @@ -284,11 +283,10 @@ void ers_report(void) void ers_force_destroy_all(void) { - int i; - - for (i = 0; i < ERS_ROOT_SIZE; i++) - if (ERS_Root[i] != NULL) - ers_free_cache(ERS_Root[i]); + ers_cache_t *cache; + + for (cache = CacheList; cache; cache = cache->Next) + ers_free_cache(cache, false); } #endif |