Clarify shared string semantics

Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
Nicholas Van Sickle
2021-12-13 09:11:06 -08:00
parent e080ade885
commit 0216d0ae9f
6 changed files with 30 additions and 33 deletions
@@ -61,7 +61,7 @@ namespace AZ::Dom
return m_children;
}
Value::Value(AZStd::shared_ptr<AZStd::string> string)
Value::Value(AZStd::shared_ptr<const AZStd::string> string)
: m_value(string)
{
}
@@ -233,7 +233,7 @@ namespace AZ::Dom
case 4: // bool
return AZStd::get<bool>(m_value) ? Type::True : Type::False;
case 5: // AZStd::string_view
case 6: // AZStd::shared_ptr<AZStd::string>
case 6: // AZStd::shared_ptr<const AZStd::string>
case 7: // ShortStringType
return Type::String;
case 8: // ObjectPtr
@@ -900,7 +900,7 @@ namespace AZ::Dom
m_value = aznumeric_cast<double>(value);
}
void Value::SetString(AZStd::shared_ptr<AZStd::string> string)
void Value::SetString(AZStd::shared_ptr<const AZStd::string> string)
{
m_value = string;
}
@@ -911,8 +911,8 @@ namespace AZ::Dom
{
case 5: // AZStd::string_view
return AZStd::get<AZStd::string_view>(m_value);
case 6: // AZStd::shared_ptr<AZStd::string>
return *AZStd::get<AZStd::shared_ptr<AZStd::string>>(m_value);
case 6: // AZStd::shared_ptr<const AZStd::string>
return *AZStd::get<AZStd::shared_ptr<const AZStd::string>>(m_value);
case 7: // ShortStringType
{
const ShortStringType& ShortString = AZStd::get<ShortStringType>(m_value);
@@ -948,7 +948,7 @@ namespace AZ::Dom
}
else
{
m_value = AZStd::allocate_shared<AZStd::string>(AZStdAlloc<ValueAllocator>(), value);
m_value = AZStd::allocate_shared<const AZStd::string>(AZStdAlloc<ValueAllocator>(), value);
}
}
@@ -1000,7 +1000,7 @@ namespace AZ::Dom
{
result = visitor.String(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
}
else if constexpr (AZStd::is_same_v<Alternative, AZStd::shared_ptr<AZStd::string>>)
else if constexpr (AZStd::is_same_v<Alternative, AZStd::shared_ptr<const AZStd::string>>)
{
result = visitor.RefCountedString(arg, copyStrings ? Lifetime::Temporary : Lifetime::Persistent);
}
@@ -1096,7 +1096,7 @@ namespace AZ::Dom
if (IsString() && other.IsString())
{
// If we both hold the same ref counted string we don't need to do a full comparison
if (AZStd::holds_alternative<AZStd::shared_ptr<AZStd::string>>(m_value) && m_value == other.m_value)
if (AZStd::holds_alternative<AZStd::shared_ptr<const AZStd::string>>(m_value) && m_value == other.m_value)
{
return true;
}
+11 -19
View File
@@ -39,8 +39,7 @@ namespace AZ::Dom
};
//! The allocator used by Value.
//! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside the vector
//! contents of its container storage.
//! Value heap allocates shared_ptrs for its container storage (Array / Object / Node) alongside
class ValueAllocator final : public SimpleSchemaAllocator<AZ::HphaSchema, AZ::HphaSchema::Descriptor, false, false>
{
public:
@@ -131,7 +130,7 @@ namespace AZ::Dom
Value(const Value&);
Value(Value&&) noexcept;
Value(AZStd::string_view string, bool copy);
Value(AZStd::shared_ptr<AZStd::string> string);
Value(AZStd::shared_ptr<const AZStd::string> string);
Value(int32_t value);
Value(uint32_t value);
@@ -242,10 +241,6 @@ namespace AZ::Dom
const Array::ContainerType& GetArray() const;
// Node API (supports both object + array API, plus a dedicated NodeName)...
// bool CanConvertToNodeFromObject() const;
// Value& ConvertToNodeFromObject();
// Value& ConvertToObjectFromNode();
void SetNode(AZ::Name name);
void SetNode(AZStd::string_view name);
@@ -282,14 +277,14 @@ namespace AZ::Dom
float GetFloat() const;
void SetFloat(float);
// string API...
// String API...
AZStd::string_view GetString() const;
size_t GetStringLength() const;
void SetString(AZStd::string_view);
void SetString(AZStd::shared_ptr<AZStd::string>);
void SetString(AZStd::shared_ptr<const AZStd::string>);
void CopyFromString(AZStd::string_view);
// opaque type API...
// Opaque type API...
AZStd::any& GetOpaqueValue() const;
//! This sets this Value to represent a value of an type that the DOM has
//! no formal knowledge of. Where possible, it should be preferred to
@@ -298,10 +293,10 @@ namespace AZ::Dom
//! values.
void SetOpaqueValue(AZStd::any&);
// null API...
// Null API...
void SetNull();
// Visitor API
// Visitor API...
Visitor::Result Accept(Visitor& visitor, bool copyStrings) const;
AZStd::unique_ptr<Visitor> GetWriteHandler();
@@ -330,12 +325,9 @@ namespace AZ::Dom
}
};
// If using the the copy on write model, anything stored internally as a shared_ptr will
// detach and copy when doing a mutating operation if use_count() > 1.
// This internal storage will not have a 1:1 mapping to the public Type, as there may be
// multiple storage options (e.g. strings being stored as non-owning string_view or
// owning shared_ptr<string>)
//! The internal storage type for Value.
//! These types do not correspond one-to-one with the Value's external Type as there may be multiple storage classes
//! for the same type in some instances, such as string storage
using ValueType = AZStd::variant<
// NullType
AZStd::monostate,
@@ -347,7 +339,7 @@ namespace AZ::Dom
bool,
// StringType
AZStd::string_view,
AZStd::shared_ptr<AZStd::string>,
AZStd::shared_ptr<const AZStd::string>,
ShortStringType,
// ObjectType
ObjectPtr,
@@ -68,7 +68,7 @@ namespace AZ::Dom
return FinishWrite();
}
Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr<AZStd::string> value, [[maybe_unused]] Lifetime lifetime)
Visitor::Result ValueWriter::RefCountedString(AZStd::shared_ptr<const AZStd::string> value, [[maybe_unused]] Lifetime lifetime)
{
CurrentValue().SetString(value);
return FinishWrite();
@@ -26,7 +26,7 @@ namespace AZ::Dom
Result Double(double value) override;
Result String(AZStd::string_view value, Lifetime lifetime) override;
Result RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime) override;
Result RefCountedString(AZStd::shared_ptr<const AZStd::string> value, Lifetime lifetime) override;
Result StartObject() override;
Result EndObject(AZ::u64 attributeCount) override;
Result Key(AZ::Name key) override;
@@ -105,7 +105,7 @@ namespace AZ::Dom
return VisitorSuccess();
}
Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime)
Visitor::Result Visitor::RefCountedString(AZStd::shared_ptr<const AZStd::string> value, Lifetime lifetime)
{
return String(*value, lifetime);
}
@@ -168,10 +168,15 @@ namespace AZ::Dom
virtual Result Uint64(AZ::u64 value);
//! Operates on a double precision, 64 bit floating point value.
virtual Result Double(double value);
//! Operates on a string value. As strings are a reference type.
//! Storage semantics are provided to indicate where the value may be stored persistently or requires a copy.
//! Operates on a string value. As strings are a reference type,
//! storage semantics are provided to indicate where the value may be stored persistently or requires a copy.
//! \param lifetime Specifies the lifetime of this string - if the string has a temporary lifetime, it cannot
//! safely be stored as a reference.
virtual Result String(AZStd::string_view value, Lifetime lifetime);
virtual Result RefCountedString(AZStd::shared_ptr<AZStd::string> value, Lifetime lifetime);
//! Operates on a ref-counted string value. S
//! \param lifetime Specifies the lifetime of this string. If the string has a temporary lifetime, it may not
//! be safely stored as a reference, but may still be safely stored as a ref-counted shared_ptr.
virtual Result RefCountedString(AZStd::shared_ptr<const AZStd::string> value, Lifetime lifetime);
//! Operates on an opaque value. As opaque values are a reference type, storage semantics are provided to
//! indicate where the value may be stored persistently or requires a copy.
//! The base implementation of OpaqueValue rejects the operation, as opaque values are meant for special