refactor(Placeholder): more SOO consolidation and optimization

This commit is contained in:
Alex Fabijanic 2022-04-19 09:03:47 +00:00
parent 45cbee7c0e
commit a1819107de
6 changed files with 29 additions and 122 deletions

View File

@ -97,8 +97,8 @@ public:
bool isEmpty() const
{
char buf[POCO_SMALL_OBJECT_SIZE] = {};
return 0 == std::memcmp(holder, buf, POCO_SMALL_OBJECT_SIZE);
char buf[SizeV] = {};
return 0 == std::memcmp(holder, buf, SizeV);
}
bool isLocal() const
@ -106,13 +106,9 @@ public:
return holder[SizeV] != 0;
}
void setLocal(bool local) const
{
holder[SizeV] = local ? 1 : 0;
}
template <typename T, typename V>
PlaceholderT* assignStack(const V& value)
template<typename T, typename V,
typename std::enable_if<TypeSizeLE<T, Placeholder::Size::value>::value>::type* = nullptr>
PlaceholderT* assign(const V& value)
{
erase();
new (reinterpret_cast<PlaceholderT*>(holder)) T(value);
@ -120,8 +116,9 @@ public:
return reinterpret_cast<PlaceholderT*>(holder);
}
template <typename T, typename V>
PlaceholderT* assignHeap(const V& value)
template<typename T, typename V,
typename std::enable_if<TypeSizeGT<T, Placeholder::Size::value>::value>::type* = nullptr>
PlaceholderT* assign(const V& value)
{
erase();
pHolder = new T(value);
@ -140,6 +137,11 @@ public:
private:
typedef typename std::aligned_storage<SizeV+1>::type AlignerType;
void setLocal(bool local) const
{
holder[SizeV] = local ? 1 : 0;
}
void destruct(bool clear)
{
if (!isEmpty())
@ -189,13 +191,7 @@ private:
}
template <typename T, typename V>
PlaceholderT* assignStack(const V& value)
{
return assignHeap<T, V>(value);
}
template <typename T, typename V>
PlaceholderT* assignHeap(const V& value)
PlaceholderT* assign(const V& value)
{
erase();
return pHolder = new T(value);
@ -346,27 +342,13 @@ private:
virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
{
cloneSOO(pPlaceholder, _held);
pPlaceholder->assign<Holder<ValueType>, ValueType>(_held);
}
ValueType _held;
private:
template<typename VT,
typename std::enable_if<TypeSizeLE<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr>
static void cloneSOO(Placeholder<ValueHolder>* pPlaceholder, VT& held)
{
pPlaceholder->assignStack<Holder<ValueType>, ValueType>(held);
}
template<typename VT,
typename std::enable_if<TypeSizeGT<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr>
static void cloneSOO(Placeholder<ValueHolder>* pPlaceholder, VT& held)
{
pPlaceholder->assignHeap<Holder<ValueType>, ValueType>(held);
}
Holder & operator = (const Holder &);
};
@ -375,18 +357,10 @@ private:
return _valueHolder.content();
}
template<typename ValueType,
typename std::enable_if<TypeSizeLE<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
template<typename ValueType>
void construct(const ValueType& value)
{
_valueHolder.assignStack<Holder<ValueType>, ValueType>(value);
}
template<typename ValueType,
typename std::enable_if<TypeSizeGT<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
void construct(const ValueType& value)
{
_valueHolder.assignHeap<Holder<ValueType>, ValueType>(value);
_valueHolder.assign<Holder<ValueType>, ValueType>(value);
}
void construct(const Any& other)

View File

@ -71,12 +71,7 @@
// cases when value holder fits into POCO_SMALL_OBJECT_SIZE
// (see below).
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! NOTE: Any/Dynamic::Var SOO will NOT work reliably !!!
// !!! without C++11 (std::aligned_storage in particular). !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
//#define POCO_NO_SOO
// #define POCO_NO_SOO
// Small object size in bytes. When assigned to Any or Var,

View File

@ -225,6 +225,7 @@ public:
Var& operator = (const T& other)
/// Assignment operator for assigning POD to Var
{
clear();
construct(other);
return *this;
}
@ -610,35 +611,20 @@ private:
{
}
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)
{
constructSOO(value);
_placeholder.assign<VarHolderImpl<ValueType>, ValueType>(value);
}
void construct(const char* value)
{
std::string val(value);
constructSOO(val);
_placeholder.assign<VarHolderImpl<std::string>, std::string>(val);
}
void construct(const Var& other)
{
_placeholder.erase();
if (!other.isEmpty())
other.content()->clone(&_placeholder);
}

View File

@ -306,7 +306,7 @@ protected:
/// pre-allocated buffer inside the holder).
{
poco_check_ptr (pVarHolder);
return makeSOOHolder(pVarHolder, val);
return pVarHolder->assign<VarHolderImpl<T>, T>(val);
}
template <typename F, typename T>
@ -406,21 +406,6 @@ protected:
}
private:
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);
}
template <typename F, typename T>
void checkUpperLimit(const F& from) const

View File

@ -52,11 +52,8 @@ Var::~Var()
Var& Var::operator = (const Var& rhs)
{
if (this == &rhs) return *this;
if (!rhs.isEmpty())
construct(rhs);
else
_placeholder.erase();
clear();
if (!rhs.isEmpty()) construct(rhs);
return *this;
}

View File

@ -281,73 +281,43 @@ void AnyTest::testPlaceholder()
assertTrue(ph.isEmpty());
assertFalse(ph.isLocal());
char c = *ph.assignStack<char, char>(1);
char c = *ph.assign<char, char>(1);
assertTrue(1 == c);
assertFalse(ph.isEmpty());
assertTrue(ph.isLocal());
c = *ph.assignHeap<char, char>(2);
assertTrue(2 == c);
assertFalse(ph.isEmpty());
assertFalse(ph.isLocal());
ph.erase();
assertTrue(ph.isEmpty());
assertFalse(ph.isLocal());
if (sizeof(std::shared_ptr<int>) <= POCO_SMALL_OBJECT_SIZE)
{
Placeholder<std::shared_ptr<int>> sph;
assertTrue(sph.isEmpty());
assertFalse(sph.isLocal());
int i = **sph.assignStack<std::shared_ptr<int>, int*>(new int(1));
int i = **sph.assign<std::shared_ptr<int>, int*>(new int(1));
assertTrue(1 == i);
assertFalse(sph.isEmpty());
assertTrue(sph.isLocal());
i = **sph.assignHeap<std::shared_ptr<int>, int*>(new int(1));
assertTrue(1 == i);
assertFalse(sph.isEmpty());
assertFalse(sph.isLocal());
}
if (sizeof(Poco::SharedPtr<int>) <= POCO_SMALL_OBJECT_SIZE)
{
Placeholder<Poco::SharedPtr<int>> psph;
assertTrue(psph.isEmpty());
assertFalse(psph.isLocal());
int i = **psph.assignStack<Poco::SharedPtr<int>, int*>(new int(1));
assertTrue(1 == i);
i = **psph.assign<Poco::SharedPtr<int>, int*>(new int(2));
assertTrue(2 == i);
assertFalse(psph.isEmpty());
assertTrue(psph.isLocal());
i = **psph.assignHeap<Poco::SharedPtr<int>, int*>(new int(1));
assertTrue(1 == i);
assertFalse(psph.isEmpty());
assertFalse(psph.isLocal());
}
if (sizeof(std::vector<int>) <= POCO_SMALL_OBJECT_SIZE)
{
Placeholder<std::vector<int>> vph;
assertTrue(vph.isEmpty());
assertFalse(vph.isLocal());
std::vector<int> inv{1,2,3};
std::vector<int> outv = *vph.assignStack<std::vector<int>, std::vector<int>>(inv);
std::vector<int> outv = *vph.assign<std::vector<int>, std::vector<int>>(inv);
assertTrue(inv == outv);
assertFalse(vph.isEmpty());
assertTrue(vph.isLocal());
outv.clear();
outv = *vph.assignHeap<std::vector<int>, std::vector<int>>(inv);
assertTrue(inv == outv);
assertFalse(vph.isEmpty());
assertFalse(vph.isLocal());
}
// ...
#endif
}