roll back changes to simFieldDictionary as it doesn't want to play nice and causing corruption

This commit is contained in:
Jeff Hutchinson 2017-11-12 13:39:14 -05:00
parent d666322a1b
commit c7e12d3be7
3 changed files with 1259 additions and 1269 deletions

View file

@ -32,6 +32,10 @@
#include "console/consoleInternal.h" #include "console/consoleInternal.h"
#include "core/frameAllocator.h" #include "core/frameAllocator.h"
SimFieldDictionary::Entry *SimFieldDictionary::smFreeList = NULL;
static Chunker<SimFieldDictionary::Entry> fieldChunker;
U32 SimFieldDictionary::getHashValue(StringTableEntry slotName) U32 SimFieldDictionary::getHashValue(StringTableEntry slotName)
{ {
return HashPointer(slotName) % HashTableSize; return HashPointer(slotName) % HashTableSize;
@ -44,43 +48,58 @@ U32 SimFieldDictionary::getHashValue(const String& fieldName)
SimFieldDictionary::Entry *SimFieldDictionary::addEntry(U32 bucket, StringTableEntry slotName, ConsoleBaseType* type, char* value) SimFieldDictionary::Entry *SimFieldDictionary::addEntry(U32 bucket, StringTableEntry slotName, ConsoleBaseType* type, char* value)
{ {
Entry ret; Entry* ret;
ret.slotName = slotName; if (smFreeList)
ret.type = type; {
ret.value = value; ret = smFreeList;
smFreeList = ret->next;
}
else
ret = fieldChunker.alloc();
ret->next = mHashTable[bucket];
ret->slotName = slotName;
ret->type = type;
ret->value = value;
mHashTable[bucket] = ret;
mNumFields++; mNumFields++;
mVersion++; mVersion++;
mHashTable[bucket].push_back(std::move(ret)); return ret;
return &mHashTable[bucket].back();
} }
void SimFieldDictionary::freeEntry(SimFieldDictionary::Entry *ent) void SimFieldDictionary::freeEntry(SimFieldDictionary::Entry *ent)
{ {
auto &vec = mHashTable[getHashValue(ent->slotName)]; ent->next = smFreeList;
smFreeList = ent;
// Find the slot. mNumFields--;
auto iter = std::find_if(vec.begin(), vec.end(), [&](const Entry &ref) -> bool {
return ref.slotName == ent->slotName;
});
if (iter != vec.end())
{
vec.erase(iter);
mNumFields--;
}
} }
SimFieldDictionary::SimFieldDictionary() SimFieldDictionary::SimFieldDictionary()
: mNumFields(0), : mNumFields(0),
mVersion(0) mVersion(0)
{ {
dMemset(mHashTable, 0, sizeof(mHashTable));
} }
SimFieldDictionary::~SimFieldDictionary() SimFieldDictionary::~SimFieldDictionary()
{ {
for (U32 i = 0; i < HashTableSize; i++)
{
for (Entry *walk = mHashTable[i]; walk;)
{
Entry *temp = walk;
walk = temp->next;
if (temp->value)
dFree(temp->value);
freeEntry(temp);
}
}
AssertFatal(mNumFields == 0, "Incorrect count on field dictionary");
} }
void SimFieldDictionary::setFieldType(StringTableEntry slotName, const char *typeString) void SimFieldDictionary::setFieldType(StringTableEntry slotName, const char *typeString)
@ -100,12 +119,12 @@ void SimFieldDictionary::setFieldType(StringTableEntry slotName, ConsoleBaseType
// If the field exists on the object, set the type // If the field exists on the object, set the type
U32 bucket = getHashValue(slotName); U32 bucket = getHashValue(slotName);
for (Entry &ref : mHashTable[bucket]) for (Entry *walk = mHashTable[bucket]; walk; walk = walk->next)
{ {
if (ref.slotName == slotName) if (walk->slotName == slotName)
{ {
// Found and type assigned, let's bail // Found and type assigned, let's bail
ref.type = type; walk->type = type;
return; return;
} }
} }
@ -118,14 +137,9 @@ U32 SimFieldDictionary::getFieldType(StringTableEntry slotName) const
{ {
U32 bucket = getHashValue(slotName); U32 bucket = getHashValue(slotName);
const std::vector<Entry> &vec = mHashTable[bucket]; for (Entry *walk = mHashTable[bucket]; walk; walk = walk->next)
size_t size = vec.size(); if (walk->slotName == slotName)
for (size_t i = 0; i < size; ++i) return walk->type ? walk->type->getTypeID() : TypeString;
{
const Entry &ref = vec[i];
if (ref.slotName == slotName)
return ref.type ? ref.type->getTypeID() : TypeString;
}
return TypeString; return TypeString;
} }
@ -134,13 +148,10 @@ SimFieldDictionary::Entry *SimFieldDictionary::findDynamicField(const String &f
{ {
U32 bucket = getHashValue(fieldName); U32 bucket = getHashValue(fieldName);
const std::vector<Entry> &vec = mHashTable[bucket]; for (Entry *walk = mHashTable[bucket]; walk; walk = walk->next)
size_t size = vec.size();
for (size_t i = 0; i < size; ++i)
{ {
const Entry &ref = vec[i]; if (fieldName.equal(walk->slotName, String::NoCase))
if (fieldName.equal(ref.slotName, String::NoCase)) return walk;
return const_cast<Entry*>(&ref);
} }
return NULL; return NULL;
@ -150,13 +161,11 @@ SimFieldDictionary::Entry *SimFieldDictionary::findDynamicField(StringTableEntry
{ {
U32 bucket = getHashValue(fieldName); U32 bucket = getHashValue(fieldName);
const std::vector<Entry> &vec = mHashTable[bucket]; for (Entry *walk = mHashTable[bucket]; walk; walk = walk->next)
size_t size = vec.size();
for (size_t i = 0; i < size; ++i)
{ {
if (vec[i].slotName == fieldName) if (walk->slotName == fieldName)
{ {
return const_cast<Entry*>(&vec[i]); return walk;
} }
} }
@ -167,43 +176,45 @@ SimFieldDictionary::Entry *SimFieldDictionary::findDynamicField(StringTableEntry
void SimFieldDictionary::setFieldValue(StringTableEntry slotName, const char *value) void SimFieldDictionary::setFieldValue(StringTableEntry slotName, const char *value)
{ {
U32 bucket = getHashValue(slotName); U32 bucket = getHashValue(slotName);
Entry **walk = &mHashTable[bucket];
while (*walk && (*walk)->slotName != slotName)
walk = &((*walk)->next);
for (Entry &ref : mHashTable[bucket]) Entry *field = *walk;
if (!value || !*value)
{ {
if (ref.slotName == slotName) if (field)
{ {
if (!value || !*value) mVersion++;
{
mVersion++;
if (ref.value) if (field->value)
dFree(ref.value); dFree(field->value);
freeEntry(&ref); *walk = field->next;
} freeEntry(field);
else
{
if (ref.value)
dFree(ref.value);
ref.value = dStrdup(value);
}
return;
} }
} }
else
{
if (field)
{
if (field->value)
dFree(field->value);
// no field, add entry. field->value = dStrdup(value);
addEntry(bucket, slotName, 0, dStrdup(value)); }
else
addEntry(bucket, slotName, 0, dStrdup(value));
}
} }
const char *SimFieldDictionary::getFieldValue(StringTableEntry slotName) const char *SimFieldDictionary::getFieldValue(StringTableEntry slotName)
{ {
U32 bucket = getHashValue(slotName); U32 bucket = getHashValue(slotName);
for (const Entry &ref : mHashTable[bucket]) for (Entry *walk = mHashTable[bucket]; walk; walk = walk->next)
if (ref.slotName == slotName) if (walk->slotName == slotName)
return ref.value; return walk->value;
return NULL; return NULL;
} }
@ -214,41 +225,41 @@ void SimFieldDictionary::assignFrom(SimFieldDictionary *dict)
for (U32 i = 0; i < HashTableSize; i++) for (U32 i = 0; i < HashTableSize; i++)
{ {
for (const Entry &ref : mHashTable[i]) for (Entry *walk = dict->mHashTable[i]; walk; walk = walk->next)
{ {
setFieldValue(ref.slotName, ref.value); setFieldValue(walk->slotName, walk->value);
setFieldType(ref.slotName, ref.type); setFieldType(walk->slotName, walk->type);
} }
} }
} }
static S32 QSORT_CALLBACK compareEntries(const void* a, const void* b) static S32 QSORT_CALLBACK compareEntries(const void* a, const void* b)
{ {
const SimFieldDictionary::Entry *fa = reinterpret_cast<const SimFieldDictionary::Entry*>(a); SimFieldDictionary::Entry *fa = *((SimFieldDictionary::Entry **)a);
const SimFieldDictionary::Entry *fb = reinterpret_cast<const SimFieldDictionary::Entry*>(b); SimFieldDictionary::Entry *fb = *((SimFieldDictionary::Entry **)b);
return dStricmp(fa->slotName, fb->slotName); return dStricmp(fa->slotName, fb->slotName);
} }
void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop) void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop)
{ {
const AbstractClassRep::FieldList &list = obj->getFieldList(); const AbstractClassRep::FieldList &list = obj->getFieldList();
Vector<Entry> flist(__FILE__, __LINE__); Vector<Entry *> flist(__FILE__, __LINE__);
for (U32 i = 0; i < HashTableSize; i++) for (U32 i = 0; i < HashTableSize; i++)
{ {
for (const Entry &walk : mHashTable[i]) for (Entry *walk = mHashTable[i]; walk; walk = walk->next)
{ {
// make sure we haven't written this out yet: // make sure we haven't written this out yet:
U32 j; U32 i;
for (j = 0; j < list.size(); j++) for (i = 0; i < list.size(); i++)
if (list[j].pFieldname == walk.slotName) if (list[i].pFieldname == walk->slotName)
break; break;
if (j != list.size()) if (i != list.size())
continue; continue;
if (!obj->writeField(walk.slotName, walk.value)) if (!obj->writeField(walk->slotName, walk->value))
continue; continue;
flist.push_back(walk); flist.push_back(walk);
@ -256,20 +267,20 @@ void SimFieldDictionary::writeFields(SimObject *obj, Stream &stream, U32 tabStop
} }
// Sort Entries to prevent version control conflicts // Sort Entries to prevent version control conflicts
dQsort(flist.address(), flist.size(), sizeof(Entry), compareEntries); dQsort(flist.address(), flist.size(), sizeof(Entry *), compareEntries);
// Save them out // Save them out
for (const Entry &ref : flist) for (Vector<Entry *>::iterator itr = flist.begin(); itr != flist.end(); itr++)
{ {
U32 nBufferSize = (dStrlen(ref.value) * 2) + dStrlen(ref.slotName) + 16; U32 nBufferSize = (dStrlen((*itr)->value) * 2) + dStrlen((*itr)->slotName) + 16;
FrameTemp<char> expandedBuffer(nBufferSize); FrameTemp<char> expandedBuffer(nBufferSize);
stream.writeTabs(tabStop + 1); stream.writeTabs(tabStop + 1);
const char *typeName = ref.type && ref.type->getTypeID() != TypeString ? ref.type->getTypeName() : ""; const char *typeName = (*itr)->type && (*itr)->type->getTypeID() != TypeString ? (*itr)->type->getTypeName() : "";
dSprintf(expandedBuffer, nBufferSize, "%s%s%s = \"", typeName, *typeName ? " " : "", ref.slotName); dSprintf(expandedBuffer, nBufferSize, "%s%s%s = \"", typeName, *typeName ? " " : "", (*itr)->slotName);
if (ref.value) if ((*itr)->value)
expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), ref.value); expandEscape((char*)expandedBuffer + dStrlen(expandedBuffer), (*itr)->value);
dStrcat(expandedBuffer, "\";\r\n"); dStrcat(expandedBuffer, "\";\r\n");
stream.write(dStrlen(expandedBuffer), expandedBuffer); stream.write(dStrlen(expandedBuffer), expandedBuffer);
@ -280,35 +291,35 @@ void SimFieldDictionary::printFields(SimObject *obj)
{ {
const AbstractClassRep::FieldList &list = obj->getFieldList(); const AbstractClassRep::FieldList &list = obj->getFieldList();
char expandedBuffer[4096]; char expandedBuffer[4096];
Vector<Entry> flist(__FILE__, __LINE__); Vector<Entry *> flist(__FILE__, __LINE__);
for (U32 i = 0; i < HashTableSize; i++) for (U32 i = 0; i < HashTableSize; i++)
{ {
for (const Entry &walk : mHashTable[i]) for (Entry *walk = mHashTable[i]; walk; walk = walk->next)
{ {
// make sure we haven't written this out yet: // make sure we haven't written this out yet:
U32 j; U32 i;
for (j = 0; j < list.size(); j++) for (i = 0; i < list.size(); i++)
if (list[i].pFieldname == walk.slotName) if (list[i].pFieldname == walk->slotName)
break; break;
if (j != list.size()) if (i != list.size())
continue; continue;
flist.push_back(walk); flist.push_back(walk);
} }
} }
dQsort(flist.address(), flist.size(), sizeof(Entry), compareEntries); dQsort(flist.address(), flist.size(), sizeof(Entry *), compareEntries);
for (const Entry &ref : flist) for (Vector<Entry *>::iterator itr = flist.begin(); itr != flist.end(); itr++)
{ {
const char* type = "string"; const char* type = "string";
if (ref.type) if ((*itr)->type)
type = ref.type->getTypeClassName(); type = (*itr)->type->getTypeClassName();
dSprintf(expandedBuffer, sizeof(expandedBuffer), " %s %s = \"", type, ref.slotName); dSprintf(expandedBuffer, sizeof(expandedBuffer), " %s %s = \"", type, (*itr)->slotName);
if (ref.value) if ((*itr)->value)
expandEscape(expandedBuffer + dStrlen(expandedBuffer), ref.value); expandEscape(expandedBuffer + dStrlen(expandedBuffer), (*itr)->value);
Con::printf("%s\"", expandedBuffer); Con::printf("%s\"", expandedBuffer);
} }
} }
@ -332,44 +343,29 @@ SimFieldDictionary::Entry *SimFieldDictionary::operator[](U32 index)
SimFieldDictionaryIterator::SimFieldDictionaryIterator(SimFieldDictionary * dictionary) SimFieldDictionaryIterator::SimFieldDictionaryIterator(SimFieldDictionary * dictionary)
{ {
mDictionary = dictionary; mDictionary = dictionary;
mHashIndex = 0; mHashIndex = -1;
mVecIndex = -1; // -1 since we immediately call operator++ mEntry = 0;
mEntry = NULL;
operator++(); operator++();
} }
SimFieldDictionary::Entry* SimFieldDictionaryIterator::operator++() SimFieldDictionary::Entry* SimFieldDictionaryIterator::operator++()
{ {
if (!mDictionary || mHashIndex >= SimFieldDictionary::HashTableSize) if (!mDictionary)
{ return(mEntry);
mEntry = NULL;
return NULL;
}
std::vector<SimFieldDictionary::Entry> &vec = mDictionary->mHashTable[mHashIndex]; if (mEntry)
mEntry = mEntry->next;
while (vec.size() == 0 && mHashIndex < (SimFieldDictionary::HashTableSize - 1)) while (!mEntry && (mHashIndex < (SimFieldDictionary::HashTableSize - 1)))
{ mEntry = mDictionary->mHashTable[++mHashIndex];
vec = mDictionary->mHashTable[++mHashIndex];
mVecIndex = 0;
}
if (mVecIndex >= vec.size() || mHashIndex >= SimFieldDictionary::HashTableSize) return(mEntry);
{
mEntry = NULL;
return NULL;
}
mEntry = &vec[mVecIndex];
++mVecIndex;
return mEntry;
} }
SimFieldDictionary::Entry* SimFieldDictionaryIterator::operator*() SimFieldDictionary::Entry* SimFieldDictionaryIterator::operator*()
{ {
return mEntry; return(mEntry);
} }
// A variation of the stock SimFieldDictionary::setFieldValue(), this method adds the // A variation of the stock SimFieldDictionary::setFieldValue(), this method adds the
// <no_replace> argument which, when true, prohibits the replacement of fields that // <no_replace> argument which, when true, prohibits the replacement of fields that
// already have a value. // already have a value.
@ -389,13 +385,13 @@ void SimFieldDictionary::setFieldValue(StringTableEntry slotName, const char *va
return; return;
U32 bucket = getHashValue(slotName); U32 bucket = getHashValue(slotName);
for (const Entry &walk : mHashTable[bucket]) Entry **walk = &mHashTable[bucket];
{ while (*walk && (*walk)->slotName != slotName)
if (walk.slotName == slotName) walk = &((*walk)->next);
{
return; Entry *field = *walk;
} if (field)
} return;
addEntry(bucket, slotName, type, dStrdup(value)); addEntry(bucket, slotName, type, dStrdup(value));
} }
@ -417,22 +413,14 @@ void SimFieldDictionary::assignFrom(SimFieldDictionary *dict, const char* filter
if (filter_len == 0) if (filter_len == 0)
{ {
for (U32 i = 0; i < HashTableSize; i++) for (U32 i = 0; i < HashTableSize; i++)
{ for (Entry *walk = dict->mHashTable[i]; walk; walk = walk->next)
for (const Entry &walk : dict->mHashTable[i]) setFieldValue(walk->slotName, walk->value, walk->type, no_replace);
{
setFieldValue(walk.slotName, walk.value, walk.type, no_replace);
}
}
} }
else else
{ {
for (U32 i = 0; i < HashTableSize; i++) for (U32 i = 0; i < HashTableSize; i++)
{ for (Entry *walk = dict->mHashTable[i]; walk; walk = walk->next)
for (const Entry &walk : dict->mHashTable[i]) if (dStrncmp(walk->slotName, filter, filter_len) == 0)
{ setFieldValue(walk->slotName, walk->value, walk->type, no_replace);
if (dStrncmp(walk.slotName, filter, filter_len) == 0)
setFieldValue(walk.slotName, walk.value, walk.type, no_replace);
}
}
} }
} }

View file

@ -32,9 +32,6 @@
class ConsoleBaseType; class ConsoleBaseType;
class SimObject; class SimObject;
#include <array>
#include <vector>
#include "core/stringTable.h" #include "core/stringTable.h"
#include "core/stream/stream.h" #include "core/stream/stream.h"
@ -54,17 +51,18 @@ public:
StringTableEntry slotName; StringTableEntry slotName;
char *value; char *value;
Entry *next;
ConsoleBaseType *type; ConsoleBaseType *type;
}; };
enum enum
{ {
HashTableSize = 19 HashTableSize = 19
}; };
//Entry *mHashTable[HashTableSize]; Entry *mHashTable[HashTableSize];
std::vector<Entry> mHashTable[HashTableSize];
private: private:
static Entry *smFreeList;
void freeEntry(Entry *entry); void freeEntry(Entry *entry);
Entry* addEntry(U32 bucket, StringTableEntry slotName, ConsoleBaseType* type, char* value = 0); Entry* addEntry(U32 bucket, StringTableEntry slotName, ConsoleBaseType* type, char* value = 0);
@ -105,7 +103,6 @@ class SimFieldDictionaryIterator
{ {
SimFieldDictionary * mDictionary; SimFieldDictionary * mDictionary;
S32 mHashIndex; S32 mHashIndex;
S32 mVecIndex;
SimFieldDictionary::Entry * mEntry; SimFieldDictionary::Entry * mEntry;
public: public:
@ -115,4 +112,4 @@ public:
}; };
#endif // _SIMFIELDDICTIONARY_H_ #endif // _SIMFIELDDICTIONARY_H_

File diff suppressed because it is too large Load diff