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