Skip to content

Commit 21da012

Browse files
committed
Dynamic::Var SOO
Dynamic::Var small object optimization and some refactoring
1 parent 54a92c5 commit 21da012

File tree

16 files changed

+401
-208
lines changed

16 files changed

+401
-208
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,6 @@ lib/
100100
lib64/
101101
pocomsg.h
102102

103+
# Temporary files #
104+
###################
105+
*.bak

Data/include/Poco/Data/Date.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ class VarHolderImpl<Poco::Data::Date>: public VarHolder
225225
val = DateTimeFormatter::format(dt, "%Y/%m/%d");
226226
}
227227

228-
VarHolder* clone() const
228+
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
229229
{
230-
return new VarHolderImpl(_val);
230+
return cloneHolder(pVarHolder, _val);
231231
}
232232

233233
const Poco::Data::Date& value() const

Data/include/Poco/Data/LOB.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,9 @@ class VarHolderImpl<Poco::Data::BLOB>: public VarHolder
272272
val.assign(_val.begin(), _val.end());
273273
}
274274

275-
VarHolder* clone() const
275+
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
276276
{
277-
return new VarHolderImpl(_val);
277+
return cloneHolder(pVarHolder, _val);
278278
}
279279

280280
const Poco::Data::BLOB& value() const
@@ -310,9 +310,9 @@ class VarHolderImpl<Poco::Data::CLOB>: public VarHolder
310310
val.assign(_val.begin(), _val.end());
311311
}
312312

313-
VarHolder* clone() const
313+
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
314314
{
315-
return new VarHolderImpl(_val);
315+
return cloneHolder(pVarHolder, _val);
316316
}
317317

318318
const Poco::Data::CLOB& value() const

Data/include/Poco/Data/Time.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,9 @@ class VarHolderImpl<Poco::Data::Time>: public VarHolder
229229
val = DateTimeFormatter::format(dt, "%H:%M:%S");
230230
}
231231

232-
VarHolder* clone() const
232+
VarHolder* clone(Placeholder<VarHolder>* pVarHolder = 0) const
233233
{
234-
return new VarHolderImpl(_val);
234+
return cloneHolder(pVarHolder, _val);
235235
}
236236

237237
const Poco::Data::Time& value() const

Foundation/include/Poco/Any.h

Lines changed: 98 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,68 @@
4848
namespace Poco {
4949

5050

51+
namespace Dynamic {
52+
53+
class Var;
54+
class VarHolder;
55+
template <class> class VarHolderImpl;
56+
57+
}
58+
59+
60+
template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
61+
union Placeholder
62+
/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
63+
/// object optimization).
64+
///
65+
/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
66+
/// it will be placement-new-allocated into the local buffer
67+
/// (i.e. there will be no heap-allocation). The local buffer size is one byte
68+
/// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
69+
/// where the object was allocated (0 => heap, 1 => local).
70+
{
71+
public:
72+
static const unsigned int SIZE = SizeV;
73+
74+
Placeholder ()
75+
{
76+
erase();
77+
}
78+
79+
void erase()
80+
{
81+
std::memset(holder, 0, sizeof(Placeholder));
82+
}
83+
84+
bool isLocal() const
85+
{
86+
return holder[SIZE] != 0;
87+
}
88+
89+
void setLocal(bool local) const
90+
{
91+
holder[SIZE] = local ? 1 : 0;
92+
}
93+
94+
PlaceholderT* content() const
95+
{
96+
if(isLocal())
97+
return reinterpret_cast<PlaceholderT*>(holder);
98+
else
99+
return pHolder;
100+
}
101+
102+
private:
103+
PlaceholderT* pHolder;
104+
mutable unsigned char holder[SIZE + 1];
105+
106+
friend class Any;
107+
friend class Dynamic::Var;
108+
friend class Dynamic::VarHolder;
109+
template <class> friend class VarHolderImpl;
110+
};
111+
112+
51113
class Any
52114
/// An Any class represents a general type and is capable of storing any type, supporting type-safe extraction
53115
/// of the internally stored data.
@@ -58,13 +120,10 @@ class Any
58120
/// Modified for small object optimization support (optionally supported through conditional compilation)
59121
/// by Alex Fabijanic.
60122
{
123+
public:
61124

62125
#ifndef POCO_NO_SOO
63126

64-
union PH;
65-
66-
public:
67-
68127
Any()
69128
/// Creates an empty any type.
70129
{
@@ -75,8 +134,8 @@ class Any
75134
/// Creates an any which stores the init parameter inside.
76135
///
77136
/// Example:
78-
/// Any a(13);
79-
/// Any a(string("12345"));
137+
/// Any a(13);
138+
/// Any a(string("12345"));
80139
{
81140
construct(value);
82141
}
@@ -89,13 +148,13 @@ class Any
89148
}
90149

91150
~Any()
92-
/// Destructor. If Any is locally held, calls Placeholder destructor;
151+
/// Destructor. If Any is locally held, calls ValueHolder destructor;
93152
/// otherwise, deletes the placeholder from the heap.
94153
{
95154
if(!empty())
96155
{
97-
if(_placeholder.isLocal())
98-
content()->~Placeholder();
156+
if(_valueHolder.isLocal())
157+
content()->~ValueHolder();
99158
else
100159
delete content();
101160
}
@@ -110,14 +169,14 @@ class Any
110169
{
111170
if (this == &other) return *this;
112171

113-
if (!_placeholder.isLocal() && !other._placeholder.isLocal())
172+
if (!_valueHolder.isLocal() && !other._valueHolder.isLocal())
114173
{
115-
std::swap(_placeholder.pHolder, other._placeholder.pHolder);
174+
std::swap(_valueHolder.pHolder, other._valueHolder.pHolder);
116175
}
117176
else
118177
{
119178
Any tmp(*this);
120-
if (_placeholder.isLocal()) this->~Any();
179+
if (_valueHolder.isLocal()) this->~Any();
121180
construct(other);
122181
other = tmp;
123182
}
@@ -143,7 +202,7 @@ class Any
143202
if ((this != &rhs) && !rhs.empty())
144203
construct(rhs);
145204
else if ((this != &rhs) && rhs.empty())
146-
_placeholder.erase();
205+
_valueHolder.erase();
147206

148207
return *this;
149208
}
@@ -152,7 +211,7 @@ class Any
152211
/// Returns true if the Any is empty.
153212
{
154213
char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
155-
return 0 == std::memcmp(_placeholder.holder, buf, POCO_SMALL_OBJECT_SIZE);
214+
return 0 == std::memcmp(_valueHolder.holder, buf, _valueHolder.SIZE);
156215
}
157216

158217
const std::type_info & type() const
@@ -166,20 +225,20 @@ class Any
166225

167226
private:
168227

169-
class Placeholder
228+
class ValueHolder
170229
{
171230
public:
172231

173-
virtual ~Placeholder()
232+
virtual ~ValueHolder()
174233
{
175234
}
176235

177236
virtual const std::type_info & type() const = 0;
178-
virtual void clone(Any::PH*) const = 0;
237+
virtual void clone(Placeholder<ValueHolder>*) const = 0;
179238
};
180239

181240
template<typename ValueType>
182-
class Holder : public Placeholder
241+
class Holder : public ValueHolder
183242
{
184243
public:
185244
Holder(const ValueType & value) : _held(value)
@@ -191,11 +250,11 @@ class Any
191250
return typeid(ValueType);
192251
}
193252

194-
virtual void clone(Any::PH* pPlaceholder) const
253+
virtual void clone(Placeholder<ValueHolder>* pPlaceholder) const
195254
{
196-
if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
255+
if ((sizeof(Holder<ValueType>) <= pPlaceholder->SIZE))
197256
{
198-
new ((Placeholder*) pPlaceholder->holder) Holder(_held);
257+
new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
199258
pPlaceholder->setLocal(true);
200259
}
201260
else
@@ -211,78 +270,40 @@ class Any
211270
Holder & operator = (const Holder &);
212271
};
213272

214-
Placeholder* content() const
273+
ValueHolder* content() const
215274
{
216-
return _placeholder.content();
275+
return _valueHolder.content();
217276
}
218277

219278
template<typename ValueType>
220279
void construct(const ValueType& value)
221280
{
222-
if (sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE)
281+
if (sizeof(Holder<ValueType>) <= _valueHolder.SIZE)
223282
{
224-
new (reinterpret_cast<Placeholder*>(_placeholder.holder)) Holder<ValueType>(value);
225-
_placeholder.setLocal(true);
283+
new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
284+
_valueHolder.setLocal(true);
226285
}
227286
else
228287
{
229-
_placeholder.pHolder = new Holder<ValueType>(value);
230-
_placeholder.setLocal(false);
288+
_valueHolder.pHolder = new Holder<ValueType>(value);
289+
_valueHolder.setLocal(false);
231290
}
232291
}
233292

234293
void construct(const Any& other)
235294
{
236295
if(!other.empty())
237-
other.content()->clone(&_placeholder);
296+
other.content()->clone(&_valueHolder);
238297
else
239-
_placeholder.erase();
298+
_valueHolder.erase();
240299
}
241-
242-
union PH
243-
/// Placeholder union. If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE
244-
/// bytes of storage, it will be placement-new-allocated into the local buffer
245-
/// (i.e. there will be no heap-allocation. The local buffer size is one byte
246-
/// larger - [POCO_SMALL_OBJECT_SIZE + 1], additional byte value indicating
247-
/// where the object was allocated (0 => heap, 1 => local).
248-
{
249-
PH ()
250-
{
251-
erase();
252-
}
253-
254-
void erase()
255-
{
256-
std::memset(holder, 0, sizeof(PH));
257-
}
258-
259-
bool isLocal() const
260-
{
261-
return holder[POCO_SMALL_OBJECT_SIZE] != 0;
262-
}
263-
264-
void setLocal(bool local) const
265-
{
266-
holder[POCO_SMALL_OBJECT_SIZE] = local ? 1 : 0;
267-
}
268-
269-
Placeholder* content() const
270-
{
271-
if(isLocal())
272-
return reinterpret_cast<Placeholder*>(holder);
273-
else
274-
return pHolder;
275-
}
276-
277-
Placeholder* pHolder;
278-
mutable unsigned char holder[POCO_SMALL_OBJECT_SIZE + 1];
279-
} _placeholder;
300+
301+
Placeholder<ValueHolder> _valueHolder;
280302

281303

282304
#else // if POCO_NO_SOO
283305

284306

285-
public:
286307
Any(): _pHolder(0)
287308
/// Creates an empty any type.
288309
{
@@ -352,19 +373,19 @@ class Any
352373
}
353374

354375
private:
355-
class Placeholder
376+
class ValueHolder
356377
{
357378
public:
358-
virtual ~Placeholder()
379+
virtual ~ValueHolder()
359380
{
360381
}
361382

362383
virtual const std::type_info& type() const = 0;
363-
virtual Placeholder* clone() const = 0;
384+
virtual ValueHolder* clone() const = 0;
364385
};
365386

366387
template <typename ValueType>
367-
class Holder: public Placeholder
388+
class Holder: public ValueHolder
368389
{
369390
public:
370391
Holder(const ValueType& value):
@@ -377,7 +398,7 @@ class Any
377398
return typeid(ValueType);
378399
}
379400

380-
virtual Placeholder* clone() const
401+
virtual ValueHolder* clone() const
381402
{
382403
return new Holder(_held);
383404
}
@@ -388,13 +409,13 @@ class Any
388409
Holder & operator=(const Holder &);
389410
};
390411

391-
Placeholder* content() const
412+
ValueHolder* content() const
392413
{
393414
return _pHolder;
394415
}
395416

396417
private:
397-
Placeholder* _pHolder;
418+
ValueHolder* _pHolder;
398419

399420
#endif // POCO_NO_SOO
400421

Foundation/include/Poco/Config.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@
9393
// (see Poco/Types.h for default values).
9494
// #define POCO_NO_SOO
9595

96+
97+
// Small object size in bytes. Where applicable (e.g.
98+
// SmallObjectAllocator<char*> specialization, Any, Var, etc)
99+
// objects longer than this value will be alocated on the heap.
100+
// See Poco/SmallObjectAllocator.h for usage of this value.
101+
#if !defined(POCO_SMALL_OBJECT_SIZE)
102+
#define POCO_SMALL_OBJECT_SIZE 32
103+
#endif
104+
105+
96106
// Following are options to remove certain features
97107
// to reduce library/executable size for smaller
98108
// embedded platforms. By enabling these options,

0 commit comments

Comments
 (0)