Changed ERS cache array to use a linked list.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16744 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
greenboxal2 2012-09-04 20:07:19 +00:00
parent ea9f31706f
commit c322db5cbf

View File

@ -57,7 +57,7 @@ struct ers_list
struct ers_list *Next; struct ers_list *Next;
}; };
typedef struct typedef struct ers_cache
{ {
// Allocated object size, including ers_list size // Allocated object size, including ers_list size
unsigned int ObjectSize; unsigned int ObjectSize;
@ -65,9 +65,6 @@ typedef struct
// Number of ers_instances referencing this // Number of ers_instances referencing this
int ReferenceCount; int ReferenceCount;
// Our index in the ERS_Root array
unsigned int Index;
// Reuse linked list // Reuse linked list
struct ers_list *ReuseList; struct ers_list *ReuseList;
@ -82,6 +79,9 @@ typedef struct
// Used objects count // Used objects count
unsigned int Used; unsigned int Used;
// Linked list
struct ers_cache *Next, *Prev;
} ers_cache_t; } ers_cache_t;
typedef struct typedef struct
@ -104,16 +104,15 @@ typedef struct
// Array containing a pointer for all ers_cache structures // 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) static ers_cache_t *ers_find_cache(unsigned int size)
{ {
int i;
ers_cache_t *cache; ers_cache_t *cache;
for (i = 0; i < ERS_ROOT_SIZE; i++) for (cache = CacheList; cache; cache = cache->Next)
if (ERS_Root[i] != NULL && ERS_Root[i]->ObjectSize == size) if (cache->ObjectSize == size)
return ERS_Root[i]; return cache;
CREATE(cache, ers_cache_t, 1); CREATE(cache, ers_cache_t, 1);
cache->ObjectSize = size; cache->ObjectSize = size;
@ -124,34 +123,34 @@ static ers_cache_t *ers_find_cache(unsigned int size)
cache->Used = 0; cache->Used = 0;
cache->Max = 0; cache->Max = 0;
for (i = 0; i < ERS_ROOT_SIZE; i++) if (CacheList == NULL)
{ {
if (ERS_Root[i] == NULL) CacheList = cache;
{
ERS_Root[i] = cache;
cache->Index = i;
break;
}
} }
else
if (i >= ERS_ROOT_SIZE)
{ {
ShowFatalError("ers_new: too many root objects, increase ERS_ROOT_SIZE.\n" CacheList->Next = cache;
"exiting the program...\n"); cache->Prev = CacheList;
exit(EXIT_FAILURE);
} }
return cache; 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; unsigned int i;
for (i = 0; i < cache->Used; i++) for (i = 0; i < cache->Used; i++)
aFree(cache->Blocks[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->Blocks);
aFree(cache); 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); ShowWarning("Memory leak detected at ERS '%s', %d objects not freed.\n", instance->Name, instance->Count);
if (--instance->Cache->ReferenceCount <= 0) if (--instance->Cache->ReferenceCount <= 0)
ers_free_cache(instance->Cache); ers_free_cache(instance->Cache, true);
aFree(instance); aFree(instance);
} }
@ -284,11 +283,10 @@ void ers_report(void)
void ers_force_destroy_all(void) void ers_force_destroy_all(void)
{ {
int i; ers_cache_t *cache;
for (i = 0; i < ERS_ROOT_SIZE; i++) for (cache = CacheList; cache; cache = cache->Next)
if (ERS_Root[i] != NULL) ers_free_cache(cache, false);
ers_free_cache(ERS_Root[i]);
} }
#endif #endif