Skip to content

Commit c032c16

Browse files
committed
refactor(Any): SOO
- encapsulate data holders - add missing gets and ops - eliminate g++ warnings with enable_if's - default enable SOO
1 parent 7ae6b60 commit c032c16

File tree

4 files changed

+112
-76
lines changed

4 files changed

+112
-76
lines changed

Foundation/include/Poco/Any.h

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ template <class T> class VarHolderImpl;
3838
}
3939

4040

41+
template <class T, std::size_t S>
42+
struct TypeSizeLE:
43+
std::integral_constant<bool, (sizeof(T) <= S)>{};
44+
45+
46+
template <class T, std::size_t S>
47+
struct TypeSizeGT:
48+
std::integral_constant<bool, (sizeof(T) > S)>{};
49+
50+
4151
#ifndef POCO_NO_SOO
4252

4353

@@ -63,11 +73,25 @@ union Placeholder
6373
erase();
6474
}
6575

76+
void swap(Placeholder& other)
77+
{
78+
if (!isLocal() && !other.isLocal())
79+
std::swap(pHolder, other.pHolder);
80+
else
81+
throw Poco::InvalidAccessException("Placeholder::swap()");
82+
}
83+
6684
void erase()
6785
{
6886
std::memset(holder, 0, sizeof(Placeholder));
6987
}
7088

89+
bool isEmpty() const
90+
{
91+
char buf[POCO_SMALL_OBJECT_SIZE] = {};
92+
return 0 == std::memcmp(holder, buf, POCO_SMALL_OBJECT_SIZE);
93+
}
94+
7195
bool isLocal() const
7296
{
7397
return holder[SizeV] != 0;
@@ -78,6 +102,22 @@ union Placeholder
78102
holder[SizeV] = local ? 1 : 0;
79103
}
80104

105+
template <typename T, typename V>
106+
PlaceholderT* assignStack(const V& value)
107+
{
108+
new (reinterpret_cast<PlaceholderT*>(holder)) T(value);
109+
setLocal(true);
110+
return reinterpret_cast<PlaceholderT*>(holder);
111+
}
112+
113+
template <typename T, typename V>
114+
PlaceholderT* assignHeap(const V& value)
115+
{
116+
pHolder = new T(value);
117+
setLocal(false);
118+
return pHolder;
119+
}
120+
81121
PlaceholderT* content() const
82122
{
83123
if (isLocal())
@@ -86,20 +126,12 @@ union Placeholder
86126
return pHolder;
87127
}
88128

89-
// MSVC71,80 won't extend friendship to nested class (Any::Holder)
90-
#if !defined(POCO_MSVC_VERSION) || (defined(POCO_MSVC_VERSION) && (POCO_MSVC_VERSION > 80))
91129
private:
92-
#endif
93-
typedef typename std::aligned_storage<SizeV + 1>::type AlignerType;
94-
95-
PlaceholderT* pHolder;
96-
mutable char holder[SizeV + 1];
97-
AlignerType aligner;
130+
typedef typename std::aligned_storage<SizeV+1>::type AlignerType;
98131

99-
friend class Any;
100-
friend class Dynamic::Var;
101-
friend class Dynamic::VarHolder;
102-
template <class> friend class Dynamic::VarHolderImpl;
132+
PlaceholderT* pHolder;
133+
mutable unsigned char holder[SizeV+1];
134+
AlignerType aligner;
103135
};
104136

105137

@@ -205,7 +237,7 @@ class Any
205237

206238
if (!_valueHolder.isLocal() && !other._valueHolder.isLocal())
207239
{
208-
std::swap(_valueHolder.pHolder, other._valueHolder.pHolder);
240+
_valueHolder.swap(other._valueHolder);
209241
}
210242
else
211243
{
@@ -252,8 +284,7 @@ class Any
252284
bool empty() const
253285
/// Returns true if the Any is empty.
254286
{
255-
char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
256-
return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE);
287+
return _valueHolder.isEmpty();
257288
}
258289

259290
const std::type_info & type() const
@@ -290,21 +321,27 @@ class Any
290321

291322
virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
292323
{
293-
if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
294-
{
295-
new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
296-
pPlaceholder->setLocal(true);
297-
}
298-
else
299-
{
300-
pPlaceholder->pHolder = new Holder(_held);
301-
pPlaceholder->setLocal(false);
302-
}
324+
cloneSOO(pPlaceholder, _held);
303325
}
304326

305327
ValueType _held;
306328

307329
private:
330+
331+
template<typename VT,
332+
typename std::enable_if<TypeSizeLE<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr>
333+
static void cloneSOO(Placeholder<ValueHolder>* pPlaceholder, VT& held)
334+
{
335+
pPlaceholder->assignStack<Holder<ValueType>, ValueType>(held);
336+
}
337+
338+
template<typename VT,
339+
typename std::enable_if<TypeSizeGT<Holder<VT>, Placeholder<VT>::Size::value>::value>::type* = nullptr>
340+
static void cloneSOO(Placeholder<ValueHolder>* pPlaceholder, VT& held)
341+
{
342+
pPlaceholder->assignHeap<Holder<ValueType>, ValueType>(held);
343+
}
344+
308345
Holder & operator = (const Holder &);
309346
};
310347

@@ -313,19 +350,18 @@ class Any
313350
return _valueHolder.content();
314351
}
315352

316-
template<typename ValueType>
353+
template<typename ValueType,
354+
typename std::enable_if<TypeSizeLE<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
317355
void construct(const ValueType& value)
318356
{
319-
if (sizeof(Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
320-
{
321-
new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
322-
_valueHolder.setLocal(true);
323-
}
324-
else
325-
{
326-
_valueHolder.pHolder = new Holder<ValueType>(value);
327-
_valueHolder.setLocal(false);
328-
}
357+
_valueHolder.assignStack<Holder<ValueType>, ValueType>(value);
358+
}
359+
360+
template<typename ValueType,
361+
typename std::enable_if<TypeSizeGT<Holder<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
362+
void construct(const ValueType& value)
363+
{
364+
_valueHolder.assignHeap<Holder<ValueType>, ValueType>(value);
329365
}
330366

331367
void construct(const Any& other)

Foundation/include/Poco/Config.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,15 @@
7474
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7575
// !!! NOTE: Any/Dynamic::Var SOO will NOT work reliably !!!
7676
// !!! without C++11 (std::aligned_storage in particular). !!!
77-
// !!! Only comment this out if your compiler has support !!!
78-
// !!! for std::aligned_storage. !!!
7977
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
8078
//
81-
#ifndef POCO_ENABLE_SOO
82-
#define POCO_NO_SOO
83-
#endif
79+
//#define POCO_NO_SOO
8480

8581

8682
// Small object size in bytes. When assigned to Any or Var,
8783
// objects larger than this value will be alocated on the heap,
8884
// while those smaller will be placement new-ed into an
89-
// internal buffer.
85+
// internal stack-auto-allocated buffer.
9086
#if !defined(POCO_SMALL_OBJECT_SIZE) && !defined(POCO_NO_SOO)
9187
#define POCO_SMALL_OBJECT_SIZE 32
9288
#endif

Foundation/include/Poco/Dynamic/Var.h

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -633,34 +633,30 @@ class Foundation_API Var
633633
return _placeholder.content();
634634
}
635635

636+
template<typename ValueType,
637+
typename std::enable_if<TypeSizeLE<VarHolderImpl<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
638+
void constructSOO(const ValueType& value)
639+
{
640+
_placeholder.assignStack<VarHolderImpl<ValueType>, ValueType>(value);
641+
}
642+
643+
template<typename ValueType,
644+
typename std::enable_if<TypeSizeGT<VarHolderImpl<ValueType>, Placeholder<ValueType>::Size::value>::value>::type* = nullptr>
645+
void constructSOO(const ValueType& value)
646+
{
647+
_placeholder.assignHeap<VarHolderImpl<ValueType>, ValueType>(value);
648+
}
649+
636650
template<typename ValueType>
637651
void construct(const ValueType& value)
638652
{
639-
if (sizeof(VarHolderImpl<ValueType>) <= Placeholder<ValueType>::Size::value)
640-
{
641-
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
642-
_placeholder.setLocal(true);
643-
}
644-
else
645-
{
646-
_placeholder.pHolder = new VarHolderImpl<ValueType>(value);
647-
_placeholder.setLocal(false);
648-
}
653+
constructSOO(value);
649654
}
650655

651656
void construct(const char* value)
652657
{
653658
std::string val(value);
654-
if (sizeof(VarHolderImpl<std::string>) <= Placeholder<std::string>::Size::value)
655-
{
656-
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
657-
_placeholder.setLocal(true);
658-
}
659-
else
660-
{
661-
_placeholder.pHolder = new VarHolderImpl<std::string>(val);
662-
_placeholder.setLocal(false);
663-
}
659+
constructSOO(val);
664660
}
665661

666662
void construct(const Var& other)
@@ -709,7 +705,7 @@ inline void Var::swap(Var& other)
709705

710706
if (!_placeholder.isLocal() && !other._placeholder.isLocal())
711707
{
712-
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
708+
_placeholder.swap(other._placeholder);
713709
}
714710
else
715711
{

Foundation/include/Poco/Dynamic/VarHolder.h

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -307,19 +307,8 @@ class Foundation_API VarHolder
307307
(void)pVarHolder;
308308
return new VarHolderImpl<T>(val);
309309
#else
310-
poco_check_ptr (pVarHolder);
311-
if ((sizeof(VarHolderImpl<T>) <= Placeholder<T>::Size::value))
312-
{
313-
new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
314-
pVarHolder->setLocal(true);
315-
return (VarHolder*) pVarHolder->holder;
316-
}
317-
else
318-
{
319-
pVarHolder->pHolder = new VarHolderImpl<T>(val);
320-
pVarHolder->setLocal(false);
321-
return pVarHolder->pHolder;
322-
}
310+
poco_check_ptr (pVarHolder);
311+
return makeSOOHolder(pVarHolder, val);
323312
#endif
324313
}
325314

@@ -420,6 +409,25 @@ class Foundation_API VarHolder
420409
}
421410

422411
private:
412+
413+
#ifndef POCO_NO_SOO
414+
template<typename T,
415+
typename std::enable_if<TypeSizeLE<VarHolderImpl<T>, Placeholder<T>::Size::value>::value>::type* = nullptr>
416+
VarHolder* makeSOOHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
417+
{
418+
poco_check_ptr (pVarHolder);
419+
return pVarHolder->assignStack<VarHolderImpl<T>, T>(val);
420+
}
421+
422+
template<typename T,
423+
typename std::enable_if<TypeSizeGT<VarHolderImpl<T>, Placeholder<T>::Size::value>::value>::type* = nullptr>
424+
VarHolder* makeSOOHolder(Placeholder<VarHolder>* pVarHolder, const T& val) const
425+
{
426+
poco_check_ptr (pVarHolder);
427+
return pVarHolder->assignHeap<VarHolderImpl<T>, T>(val);
428+
}
429+
#endif
430+
423431
template <typename F, typename T>
424432
void checkUpperLimit(const F& from) const
425433
{

0 commit comments

Comments
 (0)