mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-27 11:06:50 +01:00
refactor(Placeholder): more SOO consolidation and optimization
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -71,11 +71,6 @@
|
|||||||
// cases when value holder fits into POCO_SMALL_OBJECT_SIZE
|
// cases when value holder fits into POCO_SMALL_OBJECT_SIZE
|
||||||
// (see below).
|
// (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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user