Union with shared_ptr caused a memory leak. Prevent this using std::variant

This commit is contained in:
Deukhoofd 2019-09-19 11:02:59 +02:00
parent 458274f370
commit 6c6d977000
Signed by: Deukhoofd
GPG Key ID: ADF2E9256009EDCE
1 changed files with 30 additions and 19 deletions

View File

@ -16,14 +16,25 @@ namespace Porygon{
Dictionary
};
bool _isContentAware;
using ContentTypes = unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>*;
using KeyValueType = std::pair<shared_ptr<const ScriptType>, shared_ptr<const ScriptType>>;
bool _isContentAware = false;
TableType _tableType;
union{
shared_ptr<const ScriptType> _valueType; // numerical
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* _contentTypes = nullptr; // string keyed
std::pair<shared_ptr<const ScriptType>, shared_ptr<const ScriptType>> _keyValueType; // dictionary
};
std::variant<
shared_ptr<const ScriptType>,
ContentTypes,
KeyValueType
> _valueType, _contentTypes, _keyValueType;
[[nodiscard]] inline shared_ptr<const ScriptType> GetValueType() const{
return std::get<shared_ptr<const ScriptType>>(_valueType);
}
[[nodiscard]] inline KeyValueType GetKeyValueTypes() const{
return std::get<KeyValueType>(_keyValueType);
}
public:
explicit TableScriptType()
@ -41,7 +52,7 @@ namespace Porygon{
~TableScriptType() override {
if (_tableType == TableType::StringKeyed)
delete _contentTypes;
delete GetContentTypes();
}
[[nodiscard]] bool CanBeIterated() const final {
@ -71,7 +82,7 @@ namespace Porygon{
return indexer->GetClass() == TypeClass::Number;
}
else{
auto keyType = _keyValueType.first;
auto keyType = GetKeyValueTypes().first;
return indexer->CastableTo(keyType, false) != CastResult ::InvalidCast;
}
}
@ -89,25 +100,25 @@ namespace Porygon{
auto stringType = dynamic_pointer_cast<const StringScriptType>(indexer);
if (stringType->IsKnownAtBind() && _isContentAware){
auto h = stringType->GetHashValue();
return _contentTypes->at(h);
return GetContentTypes()->at(h);
}
return ScriptType::AnyType;
}
else if (_tableType == TableType::Numerical){
return _valueType;
return GetValueType();
}
else{
return _keyValueType.second;
return GetKeyValueTypes().second;
}
}
[[nodiscard]] shared_ptr<const ScriptType> GetIndexedType(uint32_t hash) const override {
auto lookup = Utilities::HashedString::CreateLookup(hash);
return _contentTypes->at(lookup);
return GetContentTypes()->at(lookup);
}
unordered_map<Utilities::HashedString, shared_ptr<const ScriptType>>* GetContentTypes() const{
return _contentTypes;
[[nodiscard]] inline ContentTypes GetContentTypes() const{
return std::get<ContentTypes>(_contentTypes);
}
[[nodiscard]]
@ -117,12 +128,12 @@ namespace Porygon{
case Unknown: return true;
case Numerical:
return indexer->GetClass() == TypeClass ::Number &&
val->CastableTo(_valueType, false) != CastResult ::InvalidCast;
val->CastableTo(GetValueType(), false) != CastResult ::InvalidCast;
case StringKeyed:
return indexer->GetClass() == TypeClass ::String;
case Dictionary:
return indexer->CastableTo(_keyValueType.first, false) != CastResult ::InvalidCast &&
val->CastableTo(_keyValueType.second, false) != CastResult ::InvalidCast;
return indexer->CastableTo(GetKeyValueTypes().first, false) != CastResult ::InvalidCast &&
val->CastableTo(GetKeyValueTypes().second, false) != CastResult ::InvalidCast;
}
}
@ -144,14 +155,14 @@ namespace Porygon{
auto s = dynamic_pointer_cast<const StringScriptType>(indexer);
if (s->IsKnownAtBind()){
auto key = s->GetHashValue();
_contentTypes->insert({key, val});
GetContentTypes()->insert({key, val});
}
}
}
void SetIndexValue(Utilities::HashedString indexer, shared_ptr<const ScriptType> val) const override {
if (_tableType == TableType::StringKeyed){
_contentTypes->insert({indexer, val});
GetContentTypes()->insert({indexer, val});
}
else if (_tableType == TableType::Unknown){
auto t = const_cast<TableScriptType*>(this);