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

View File

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

View File

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

View File

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

View File

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

View File

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