- Removed generational garbage collection from the string pool because it didn't

actually work.
- Turned the list of TabCommands into a TArray because I saw lots of console
  commands in the memory leak report at exit. Then I realized those were actually
  key bindings, so I changed the Bindings and DoubleBindings arrays into FString
  arrays.
- Fixed: FStringCVar was missing a destructor.
- Added TArray::Insert().
- Fixed: TArray::Delete() used memmove().
- Renamed Malloc(), Realloc(), and Calloc() to M_Malloc(), M_Realloc(), and
  M_Calloc() so that the debug versions can be defined as macros.
- Enabled the CRT's memory leak detection in WinMain().
- Moved contents of PO_DeInit() into P_FreeLevelData().
- Removed "PolyBlockMap = NULL;" from P_SetupLevel(), because the P_FreeLevelData()
  call it makes next does the exact same thing, but also freeing it if needed.
- Fixed: Unneeded memcpy in UnpackUserCmd() when ucmd and basis are the same


SVN r75 (trunk)
This commit is contained in:
Randy Heit 2006-05-04 03:49:46 +00:00
commit c8cdb52863
38 changed files with 264 additions and 242 deletions

View file

@ -31,7 +31,7 @@ struct FString::Pool
char *Realloc (char *chars, size_t newlen);
void Free (char *chars);
void MergeFreeBlocks (StringHeader *block);
void CollectGarbage (bool noGenerations);
void CollectGarbage ();
bool BigEnough (size_t len) const;
size_t RoundLen (size_t len) const;
@ -40,8 +40,6 @@ struct FString::Pool
char *PoolData;
char *MaxAlloc;
StringHeader *NextAlloc;
StringHeader *GarbageStart;
int GenerationNum;
};
// The PoolGroup does not get a constructor, because there is no way to
@ -100,13 +98,8 @@ char *FString::PoolGroup::Alloc (FString *owner, size_t len)
}
if (best->BigEnough (len))
{
best->CollectGarbage (false);
best->CollectGarbage ();
mem = best->Alloc (owner, len);
if (mem == NULL)
{
best->CollectGarbage (true);
mem = best->Alloc (owner, len);
}
// Move the pool to the front of the list
*bestprev = best->Next;
best->Next = Pools;
@ -151,7 +144,10 @@ char *FString::PoolGroup::Realloc (FString *owner, char *chars, size_t newlen)
void FString::PoolGroup::Free (char *chars)
{
Pool *pool = FindPool (chars);
pool->Free (chars);
if (pool != NULL)
{
pool->Free (chars);
}
}
FString::Pool *FString::PoolGroup::FindPool (char *chars) const
@ -187,8 +183,6 @@ FString::Pool::Pool (size_t minSize)
NextAlloc = (StringHeader *)PoolData;
NextAlloc->Owner = NULL;
NextAlloc->Len = minSize;
GarbageStart = NextAlloc;
GenerationNum = 0;
}
FString::Pool::~Pool ()
@ -199,19 +193,19 @@ FString::Pool::~Pool ()
// all the strings stored in it. So we need to walk through the pool
// and make any owned strings un-owned.
StringHeader *str;
StringHeader *laststr;
for (str = (StringHeader *)PoolData; str < NextAlloc; )
{
if (str->Owner != NULL)
{
str->Owner->Chars = NULL;
str->Owner = NULL;
str = (StringHeader *)((char *)str + RoundLen(str->Len));
}
else
{
str = (StringHeader *)((char *)str + str->Len);
FString *owner = str->Owner;
assert (owner->Chars == (char *)str + sizeof(StringHeader));
Free ((char *)str + sizeof(StringHeader));
owner->Chars = "";
}
laststr = str;
str = (StringHeader *)((char *)str + str->Len);
}
delete[] PoolData;
@ -308,6 +302,21 @@ char *FString::Pool::Realloc (char *chars, size_t newlen)
void FString::Pool::Free (char *chars)
{
#ifdef _DEBUG
for (StringHeader *str = (StringHeader *)PoolData; str < NextAlloc; )
{
if (str->Owner != NULL)
{
assert (str->Owner->Chars == (char *)str + sizeof(StringHeader));
str = (StringHeader *)((char *)str + RoundLen(str->Len));
}
else
{
str = (StringHeader *)((char *)str + str->Len);
}
}
#endif
StringHeader *head = (StringHeader *)(chars - sizeof(StringHeader));
size_t truelen = RoundLen (head->Len);
@ -316,6 +325,25 @@ void FString::Pool::Free (char *chars)
head->Owner = NULL;
head->Len = truelen;
MergeFreeBlocks (head);
#ifdef _DEBUG
memset (head + 1, 0xCE, head->Len - sizeof(StringHeader));
#endif
#ifdef _DEBUG
for (StringHeader *str = (StringHeader *)PoolData; str < NextAlloc; )
{
if (str->Owner != NULL)
{
assert (str->Owner->Chars == (char *)str + sizeof(StringHeader));
str = (StringHeader *)((char *)str + RoundLen(str->Len));
}
else
{
str = (StringHeader *)((char *)str + str->Len);
}
}
#endif
}
void FString::Pool::MergeFreeBlocks (StringHeader *head)
@ -331,10 +359,6 @@ void FString::Pool::MergeFreeBlocks (StringHeader *head)
// If this chain of blocks meets up with the free space, then they can join up with it.
if (block == NextAlloc)
{
if (GarbageStart == NextAlloc)
{
GarbageStart = head;
}
NextAlloc = head;
head->Len = MaxAlloc - (char *)head;
}
@ -354,19 +378,13 @@ size_t FString::Pool::RoundLen (size_t len) const
return (len + 1 + sizeof(StringHeader) + BLOCK_GRANULARITY - 1) & ~(BLOCK_GRANULARITY - 1);
}
void FString::Pool::CollectGarbage (bool noGenerations)
void FString::Pool::CollectGarbage ()
{
// This is a generational garbage collector. The space occupied by strings from
// the first two generations will not be collected unless noGenerations is set true.
if (noGenerations)
{
GarbageStart = (StringHeader *)PoolData;
GenerationNum = 0;
}
StringHeader *moveto, *movefrom;
moveto = movefrom = GarbageStart;
moveto = movefrom = (StringHeader *)PoolData;
while (movefrom < NextAlloc)
{
@ -397,11 +415,6 @@ void FString::Pool::CollectGarbage (bool noGenerations)
}
else if (FreeSpace != 0)
FreeSpace = FreeSpace;
if (++GenerationNum <= 3)
{
GarbageStart = moveto;
}
}
#else
char *FString::PoolGroup::Alloc (FString *owner, size_t len)