mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
- changed locking mechanism for ACS strings.
It will now store the level numbers that lock a string instead of just incrementing a counter. This should make it more robust because each level can lock a string only once and some possible leftover garbage data won't be able to cause a lock decrease when a savegame is being reloaded.
This commit is contained in:
parent
e956d19769
commit
2478cd0467
2 changed files with 58 additions and 35 deletions
|
@ -343,6 +343,23 @@ FACSStack::~FACSStack()
|
||||||
|
|
||||||
ACSStringPool GlobalACSStrings;
|
ACSStringPool GlobalACSStrings;
|
||||||
|
|
||||||
|
void ACSStringPool::PoolEntry::Lock()
|
||||||
|
{
|
||||||
|
if (Locks.Find(level.levelnum) == Locks.Size())
|
||||||
|
{
|
||||||
|
Locks.Push(level.levelnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACSStringPool::PoolEntry::Unlock()
|
||||||
|
{
|
||||||
|
auto ndx = Locks.Find(level.levelnum);
|
||||||
|
if (ndx < Locks.Size())
|
||||||
|
{
|
||||||
|
Locks.Delete(ndx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ACSStringPool::ACSStringPool()
|
ACSStringPool::ACSStringPool()
|
||||||
{
|
{
|
||||||
memset(PoolBuckets, 0xFF, sizeof(PoolBuckets));
|
memset(PoolBuckets, 0xFF, sizeof(PoolBuckets));
|
||||||
|
@ -430,7 +447,7 @@ void ACSStringPool::LockString(int strnum)
|
||||||
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
||||||
strnum &= ~LIBRARYID_MASK;
|
strnum &= ~LIBRARYID_MASK;
|
||||||
assert((unsigned)strnum < Pool.Size());
|
assert((unsigned)strnum < Pool.Size());
|
||||||
Pool[strnum].LockCount++;
|
Pool[strnum].Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
@ -446,8 +463,7 @@ void ACSStringPool::UnlockString(int strnum)
|
||||||
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
||||||
strnum &= ~LIBRARYID_MASK;
|
strnum &= ~LIBRARYID_MASK;
|
||||||
assert((unsigned)strnum < Pool.Size());
|
assert((unsigned)strnum < Pool.Size());
|
||||||
assert(Pool[strnum].LockCount > 0);
|
Pool[strnum].Unlock();
|
||||||
Pool[strnum].LockCount--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
@ -464,7 +480,7 @@ void ACSStringPool::MarkString(int strnum)
|
||||||
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
assert((strnum & LIBRARYID_MASK) == STRPOOL_LIBRARYID_OR);
|
||||||
strnum &= ~LIBRARYID_MASK;
|
strnum &= ~LIBRARYID_MASK;
|
||||||
assert((unsigned)strnum < Pool.Size());
|
assert((unsigned)strnum < Pool.Size());
|
||||||
Pool[strnum].LockCount |= 0x80000000;
|
Pool[strnum].Mark = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
@ -489,7 +505,7 @@ void ACSStringPool::LockStringArray(const int *strnum, unsigned int count)
|
||||||
num &= ~LIBRARYID_MASK;
|
num &= ~LIBRARYID_MASK;
|
||||||
if ((unsigned)num < Pool.Size())
|
if ((unsigned)num < Pool.Size())
|
||||||
{
|
{
|
||||||
Pool[num].LockCount++;
|
Pool[num].Lock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,8 +529,7 @@ void ACSStringPool::UnlockStringArray(const int *strnum, unsigned int count)
|
||||||
num &= ~LIBRARYID_MASK;
|
num &= ~LIBRARYID_MASK;
|
||||||
if ((unsigned)num < Pool.Size())
|
if ((unsigned)num < Pool.Size())
|
||||||
{
|
{
|
||||||
assert(Pool[num].LockCount > 0);
|
Pool[num].Unlock();
|
||||||
Pool[num].LockCount--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -538,7 +553,7 @@ void ACSStringPool::MarkStringArray(const int *strnum, unsigned int count)
|
||||||
num &= ~LIBRARYID_MASK;
|
num &= ~LIBRARYID_MASK;
|
||||||
if ((unsigned)num < Pool.Size())
|
if ((unsigned)num < Pool.Size())
|
||||||
{
|
{
|
||||||
Pool[num].LockCount |= 0x80000000;
|
Pool[num].Mark = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,7 +580,7 @@ void ACSStringPool::MarkStringMap(const FWorldGlobalArray &aray)
|
||||||
num &= ~LIBRARYID_MASK;
|
num &= ~LIBRARYID_MASK;
|
||||||
if ((unsigned)num < Pool.Size())
|
if ((unsigned)num < Pool.Size())
|
||||||
{
|
{
|
||||||
Pool[num].LockCount |= 0x80000000;
|
Pool[num].Mark |= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,7 +599,8 @@ void ACSStringPool::UnlockAll()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < Pool.Size(); ++i)
|
for (unsigned int i = 0; i < Pool.Size(); ++i)
|
||||||
{
|
{
|
||||||
Pool[i].LockCount = 0;
|
Pool[i].Mark = false;
|
||||||
|
Pool[i].Locks.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,7 +623,7 @@ void ACSStringPool::PurgeStrings()
|
||||||
PoolEntry *entry = &Pool[i];
|
PoolEntry *entry = &Pool[i];
|
||||||
if (entry->Next != FREE_ENTRY)
|
if (entry->Next != FREE_ENTRY)
|
||||||
{
|
{
|
||||||
if (entry->LockCount == 0)
|
if (entry->Locks.Size() == 0 && !entry->Mark)
|
||||||
{
|
{
|
||||||
freedcount++;
|
freedcount++;
|
||||||
// Mark this entry as free.
|
// Mark this entry as free.
|
||||||
|
@ -627,7 +643,7 @@ void ACSStringPool::PurgeStrings()
|
||||||
entry->Next = PoolBuckets[h];
|
entry->Next = PoolBuckets[h];
|
||||||
PoolBuckets[h] = i;
|
PoolBuckets[h] = i;
|
||||||
// Remove MarkString's mark.
|
// Remove MarkString's mark.
|
||||||
entry->LockCount &= 0x7FFFFFFF;
|
entry->Mark = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -692,7 +708,8 @@ int ACSStringPool::InsertString(FString &str, unsigned int h, unsigned int bucke
|
||||||
entry->Str = str;
|
entry->Str = str;
|
||||||
entry->Hash = h;
|
entry->Hash = h;
|
||||||
entry->Next = PoolBuckets[bucketnum];
|
entry->Next = PoolBuckets[bucketnum];
|
||||||
entry->LockCount = 0;
|
entry->Mark = false;
|
||||||
|
entry->Locks.Clear();
|
||||||
PoolBuckets[bucketnum] = index;
|
PoolBuckets[bucketnum] = index;
|
||||||
return index | STRPOOL_LIBRARYID_OR;
|
return index | STRPOOL_LIBRARYID_OR;
|
||||||
}
|
}
|
||||||
|
@ -735,7 +752,8 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
|
||||||
for (auto &p : Pool)
|
for (auto &p : Pool)
|
||||||
{
|
{
|
||||||
p.Next = FREE_ENTRY;
|
p.Next = FREE_ENTRY;
|
||||||
p.LockCount = 0;
|
p.Mark = false;
|
||||||
|
p.Locks.Clear();
|
||||||
}
|
}
|
||||||
if (file.BeginArray("pool"))
|
if (file.BeginArray("pool"))
|
||||||
{
|
{
|
||||||
|
@ -749,7 +767,7 @@ void ACSStringPool::ReadStrings(FSerializer &file, const char *key)
|
||||||
if (ii < Pool.Size())
|
if (ii < Pool.Size())
|
||||||
{
|
{
|
||||||
file("string", Pool[ii].Str)
|
file("string", Pool[ii].Str)
|
||||||
("lockcount", Pool[ii].LockCount);
|
("locks", Pool[ii].Locks);
|
||||||
|
|
||||||
unsigned h = SuperFastHash(Pool[ii].Str, Pool[ii].Str.Len());
|
unsigned h = SuperFastHash(Pool[ii].Str, Pool[ii].Str.Len());
|
||||||
unsigned bucketnum = h % NUM_BUCKETS;
|
unsigned bucketnum = h % NUM_BUCKETS;
|
||||||
|
@ -792,13 +810,9 @@ void ACSStringPool::WriteStrings(FSerializer &file, const char *key) const
|
||||||
{
|
{
|
||||||
if (file.BeginObject(nullptr))
|
if (file.BeginObject(nullptr))
|
||||||
{
|
{
|
||||||
if (i == 430)
|
|
||||||
{
|
|
||||||
int a = 0;
|
|
||||||
}
|
|
||||||
file("index", i)
|
file("index", i)
|
||||||
("string", entry->Str)
|
("string", entry->Str)
|
||||||
("lockcount", entry->LockCount)
|
("locks", entry->Locks)
|
||||||
.EndObject();
|
.EndObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -823,12 +837,28 @@ void ACSStringPool::Dump() const
|
||||||
{
|
{
|
||||||
if (Pool[i].Next != FREE_ENTRY)
|
if (Pool[i].Next != FREE_ENTRY)
|
||||||
{
|
{
|
||||||
Printf("%4u. (%2d) \"%s\"\n", i, Pool[i].LockCount, Pool[i].Str.GetChars());
|
Printf("%4u. (%2d) \"%s\"\n", i, Pool[i].Locks.Size(), Pool[i].Str.GetChars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Printf("First free %u\n", FirstFreeEntry);
|
Printf("First free %u\n", FirstFreeEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACSStringPool::UnlockForLevel(int lnum)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < Pool.Size(); ++i)
|
||||||
|
{
|
||||||
|
if (Pool[i].Next != FREE_ENTRY)
|
||||||
|
{
|
||||||
|
auto ndx = Pool[i].Locks.Find(lnum);
|
||||||
|
if (ndx < Pool[i].Locks.Size())
|
||||||
|
{
|
||||||
|
Pool[i].Locks.Delete(ndx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// P_MarkWorldVarStrings
|
// P_MarkWorldVarStrings
|
||||||
|
@ -1573,19 +1603,7 @@ void FBehavior::StaticLockLevelVarStrings()
|
||||||
|
|
||||||
void FBehavior::StaticUnlockLevelVarStrings()
|
void FBehavior::StaticUnlockLevelVarStrings()
|
||||||
{
|
{
|
||||||
// Unlock map variables.
|
GlobalACSStrings.UnlockForLevel(level.levelnum);
|
||||||
for (DWORD modnum = 0; modnum < StaticModules.Size(); ++modnum)
|
|
||||||
{
|
|
||||||
StaticModules[modnum]->UnlockMapVarStrings();
|
|
||||||
}
|
|
||||||
// Unlock running scripts' local variables.
|
|
||||||
if (DACSThinker::ActiveThinker != NULL)
|
|
||||||
{
|
|
||||||
for (DLevelScript *script = DACSThinker::ActiveThinker->Scripts; script != NULL; script = script->GetNext())
|
|
||||||
{
|
|
||||||
script->UnlockLocalVarStrings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FBehavior::MarkMapVarStrings() const
|
void FBehavior::MarkMapVarStrings() const
|
||||||
|
|
|
@ -95,6 +95,7 @@ public:
|
||||||
void PurgeStrings();
|
void PurgeStrings();
|
||||||
void Clear();
|
void Clear();
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
|
void UnlockForLevel(int level) ;
|
||||||
void ReadStrings(FSerializer &file, const char *key);
|
void ReadStrings(FSerializer &file, const char *key);
|
||||||
void WriteStrings(FSerializer &file, const char *key) const;
|
void WriteStrings(FSerializer &file, const char *key) const;
|
||||||
|
|
||||||
|
@ -112,7 +113,11 @@ private:
|
||||||
FString Str;
|
FString Str;
|
||||||
unsigned int Hash;
|
unsigned int Hash;
|
||||||
unsigned int Next;
|
unsigned int Next;
|
||||||
unsigned int LockCount;
|
bool Mark;
|
||||||
|
TArray<int> Locks;
|
||||||
|
|
||||||
|
void Lock();
|
||||||
|
void Unlock();
|
||||||
};
|
};
|
||||||
TArray<PoolEntry> Pool;
|
TArray<PoolEntry> Pool;
|
||||||
unsigned int PoolBuckets[NUM_BUCKETS];
|
unsigned int PoolBuckets[NUM_BUCKETS];
|
||||||
|
|
Loading…
Reference in a new issue