Refactor/any soo (#3564)

* refactor(Any): SOO

- encapsulate data holders
- add missing gets and ops
- eliminate g++ warnings with enable_if's
- default enable SOO

* refactor(Placeholder): encapsulate SOO memory management and fix leaks; cf. #3297 #3514

* fix(Placeholder): asan errors and add tests

cf. #3297 #3514
This commit is contained in:
Aleksandar Fabijanic
2022-04-16 06:38:55 -05:00
committed by GitHub
parent 7ae6b60e9f
commit 9c976da830
9 changed files with 264 additions and 119 deletions

View File

@@ -621,10 +621,10 @@ private:
void destruct()
{
if (!isEmpty()) delete content();
delete _pHolder;
}
VarHolder* _pHolder;
VarHolder* _pHolder = nullptr;
#else
@@ -633,53 +633,41 @@ private:
return _placeholder.content();
}
void destruct()
{
}
template<typename ValueType,
typename std::enable_if<TypeSizeLE<VarHolderImpl<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
void constructSOO(const ValueType& value)
{
_placeholder.assignStack<VarHolderImpl<ValueType>, ValueType>(value);
}
template<typename ValueType,
typename std::enable_if<TypeSizeGT<VarHolderImpl<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
void constructSOO(const ValueType& value)
{
_placeholder.assignHeap<VarHolderImpl<ValueType>, ValueType>(value);
}
template<typename ValueType>
void construct(const ValueType& value)
{
if (sizeof(VarHolderImpl<ValueType>) <= Placeholder<ValueType>::Size::value)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
_placeholder.setLocal(true);
}
else
{
_placeholder.pHolder = new VarHolderImpl<ValueType>(value);
_placeholder.setLocal(false);
}
constructSOO(value);
}
void construct(const char* value)
{
std::string val(value);
if (sizeof(VarHolderImpl<std::string>) <= Placeholder<std::string>::Size::value)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
_placeholder.setLocal(true);
}
else
{
_placeholder.pHolder = new VarHolderImpl<std::string>(val);
_placeholder.setLocal(false);
}
constructSOO(val);
}
void construct(const Var& other)
{
_placeholder.erase();
if (!other.isEmpty())
other.content()->clone(&_placeholder);
else
_placeholder.erase();
}
void destruct()
{
if (!isEmpty())
{
if (_placeholder.isLocal())
content()->~VarHolder();
else
delete content();
}
}
Placeholder<VarHolder> _placeholder;
@@ -709,14 +697,13 @@ inline void Var::swap(Var& other)
if (!_placeholder.isLocal() && !other._placeholder.isLocal())
{
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
_placeholder.swap(other._placeholder);
}
else
{
Var tmp(*this);
try
{
if (_placeholder.isLocal()) destruct();
construct(other);
other = tmp;
}

View File

@@ -295,31 +295,22 @@ protected:
template <typename T>
VarHolder* cloneHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
/// Instantiates value holder wrapper. If size of the wrapper is
/// larger than POCO_SMALL_OBJECT_SIZE, holder is instantiated on
/// Instantiates value holder wrapper.
///
/// Called from clone() member function of the implementation.
///
/// When the smal object optimization is enabled (POCO_NO_SOO not
/// defined), if size of the wrapper is larger than
/// POCO_SMALL_OBJECT_SIZE, holder is instantiated on
/// the heap, otherwise it is instantiated in-place (in the
/// pre-allocated buffer inside the holder).
///
/// Called from clone() member function of the implementation when
/// small object optimization is enabled.
{
#ifdef POCO_NO_SOO
(void)pVarHolder;
return new VarHolderImpl<T>(val);
#else
poco_check_ptr (pVarHolder);
if ((sizeof(VarHolderImpl<T>) <= Placeholder<T>::Size::value))
{
new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
pVarHolder->setLocal(true);
return (VarHolder*) pVarHolder->holder;
}
else
{
pVarHolder->pHolder = new VarHolderImpl<T>(val);
pVarHolder->setLocal(false);
return pVarHolder->pHolder;
}
return makeSOOHolder(pVarHolder, val);
#endif
}
@@ -420,6 +411,25 @@ protected:
}
private:
#ifndef POCO_NO_SOO
template<typename T,
typename std::enable_if<TypeSizeLE<VarHolderImpl<T>, Placeholder<T>::Size::value>::value>::type* = nullptr>
VarHolder* makeSOOHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
{
poco_check_ptr (pVarHolder);
return pVarHolder->assignStack<VarHolderImpl<T>, T>(val);
}
template<typename T,
typename std::enable_if<TypeSizeGT<VarHolderImpl<T>, Placeholder<T>::Size::value>::value>::type* = nullptr>
VarHolder* makeSOOHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
{
poco_check_ptr (pVarHolder);
return pVarHolder->assignHeap<VarHolderImpl<T>, T>(val);
}
#endif
template <typename F, typename T>
void checkUpperLimit(const F& from) const
{