removed Var iterators, fixed SOO alignment

- removed unnecessary using directives in Data library
- removed iterator pointers from Var (reduce size, always return copy)
- added Alignment header (adapted from LLVM infrastructure)
- added alignment guards to SOO implementations
This commit is contained in:
Aleksandar Fabijanic
2013-05-29 23:36:28 -05:00
parent 51fdec593e
commit e5eaffb790
19 changed files with 502 additions and 140 deletions

View File

@@ -983,6 +983,7 @@
<ClCompile Include="src\HashStatistic.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\Poco\Alignment.h" />
<ClInclude Include="include\Poco\Any.h" />
<ClInclude Include="include\Poco\Array.h" />
<ClInclude Include="include\Poco\Ascii.h" />

View File

@@ -1883,6 +1883,9 @@
<ClInclude Include="include\Poco\Optional.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
<ClInclude Include="include\Poco\Alignment.h">
<Filter>Core\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="src\pocomsg.rc">

View File

@@ -0,0 +1,230 @@
//
// Alignment.h
//
// $Id: //poco/svn/Foundation/include/Poco/Alignment.h#2 $
//
// Library: Foundation
// Package: Dynamic
// Module: Alignment
//
// Definition of the Alignment class.
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Adapted for POCO from LLVM Compiler Infrastructure code:
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source License
//
//===----------------------------------------------------------------------===//
//
// This file defines the AlignOf function that computes alignments for
// arbitrary types.
//
//===----------------------------------------------------------------------===//
#ifndef Foundation_AlignOf_INCLUDED
#define Foundation_AlignOf_INCLUDED
namespace Poco {
template <typename T>
struct AlignmentCalcImpl
{
char x;
T t;
private:
AlignmentCalcImpl() {} // Never instantiate.
};
template <typename T>
struct AlignOf
/// A templated class that contains an enum value representing
/// the alignment of the template argument. For example,
/// AlignOf<int>::Alignment represents the alignment of type "int". The
/// alignment calculated is the minimum alignment, and not necessarily
/// the "desired" alignment returned by GCC's __alignof__ (for example). Note
/// that because the alignment is an enum value, it can be used as a
/// compile-time constant (e.g., for template instantiation).
{
enum
{
Alignment = static_cast<unsigned int>(sizeof(AlignmentCalcImpl<T>) - sizeof(T))
};
enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 };
enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 };
enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 };
enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
};
template <typename T>
inline unsigned alignOf()
/// A templated function that returns the minimum alignment of
/// of a type. This provides no extra functionality beyond the AlignOf
/// class besides some cosmetic cleanliness. Example usage:
/// alignOf<int>() returns the alignment of an int.
{
return AlignOf<T>::Alignment;
}
template <size_t Alignment> struct AlignedCharArrayImpl;
/// Helper for building an aligned character array type.
///
/// This template is used to explicitly build up a collection of aligned
/// character types. We have to build these up using a macro and explicit
/// specialization to cope with old versions of MSVC and GCC where only an
/// integer literal can be used to specify an alignment constraint. Once built
/// up here, we can then begin to indirect between these using normal C++
/// template parameters.
// MSVC requires special handling here.
#ifndef _MSC_VER
#if __has_feature(cxx_alignas)
#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
template <> struct AlignedCharArrayImpl<x> \
{ \
char alignas(x) aligned; \
}
#elif defined(__GNUC__) || defined(__IBM_ATTRIBUTES)
#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
template <> struct AlignedCharArrayImpl<x> \
{ \
char aligned __attribute__((aligned(x))); \
}
#else
# error No supported align as directive.
#endif
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
#else // _MSC_VER
// We provide special variations of this template for the most common
// alignments because __declspec(align(...)) doesn't actually work when it is
// a member of a by-value function argument in MSVC, even if the alignment
// request is something reasonably like 8-byte or 16-byte.
template <> struct AlignedCharArrayImpl<1> { char aligned; };
template <> struct AlignedCharArrayImpl<2> { short aligned; };
template <> struct AlignedCharArrayImpl<4> { int aligned; };
template <> struct AlignedCharArrayImpl<8> { double aligned; };
#define POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \
template <> struct AlignedCharArrayImpl<x> { \
__declspec(align(x)) char aligned; \
}
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096);
POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192);
// Any larger and MSVC complains.
#undef POCO_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT
#endif // _MSC_VER
template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char>
union AlignedCharArrayUnion
/// This union template exposes a suitably aligned and sized character
/// array member which can hold elements of any of up to four types.
///
/// These types may be arrays, structs, or any other types. The goal is to
/// produce a union type containing a character array which, when used, forms
/// storage suitable to placement new any of these types over. Support for more
/// than four types can be added at the cost of more boiler plate.
{
private:
class AlignerImpl
{
T1 t1;
T2 t2;
T3 t3;
T4 t4;
AlignerImpl(); // Never defined or instantiated.
};
union SizerImpl
{
char arr1[sizeof(T1)];
char arr2[sizeof(T2)];
char arr3[sizeof(T3)];
char arr4[sizeof(T4)];
};
public:
char buffer[sizeof(SizerImpl)];
/// The character array buffer for use by clients.
///
/// No other member of this union should be referenced. They exist purely to
/// constrain the layout of this character array.
private:
Poco::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment> _nonceMember;
};
} // namespace Poco
#endif // Foundation_AlignOf_INCLUDED

View File

@@ -40,10 +40,13 @@
#include "Poco/Exception.h"
#include "Poco/MetaProgramming.h"
#include "Poco/Alignment.h"
#include <algorithm>
#include <typeinfo>
#include <cstring>
#ifdef POCO_ENABLE_CPP11
#include <type_traits>
#endif
namespace Poco {
@@ -64,7 +67,7 @@ template <class> class VarHolderImpl;
template <typename PlaceholderT, unsigned int SizeV = POCO_SMALL_OBJECT_SIZE>
union Placeholder
/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
/// object optimization).
/// object optimization, when enabled).
///
/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
/// it will be placement-new-allocated into the local buffer
@@ -86,23 +89,23 @@ public:
void erase()
{
std::memset(holder, 0, sizeof(Placeholder));
std::memset(holder.h, 0, sizeof(Placeholder));
}
bool isLocal() const
{
return holder[SizeV] != 0;
return holder.h[SizeV] != 0;
}
void setLocal(bool local) const
{
holder[SizeV] = local ? 1 : 0;
holder.h[SizeV] = local ? 1 : 0;
}
PlaceholderT* content() const
{
if(isLocal())
return reinterpret_cast<PlaceholderT*>(holder);
return reinterpret_cast<PlaceholderT*>(holder.h);
else
return pHolder;
}
@@ -112,9 +115,16 @@ public:
private:
#endif
PlaceholderT* pHolder;
PlaceholderT* pHolder;
#ifndef POCO_NO_SOO
mutable unsigned char holder[SizeV + 1];
#ifndef POCO_ENABLE_CPP11
#error "Any SOO can only be enabled with C++11 support"
#endif
mutable union
{
std::aligned_storage<SizeV + 1> a;
unsigned char h[SizeV + 1];
} holder;
#endif
friend class Any;
@@ -130,7 +140,7 @@ private:
template <typename PlaceholderT>
union Placeholder
/// ValueHolder union (used by Poco::Any and Poco::Dynamic::Var for small
/// object optimization).
/// object optimization, when enabled).
///
/// If Holder<Type> fits into POCO_SMALL_OBJECT_SIZE bytes of storage,
/// it will be placement-new-allocated into the local buffer
@@ -275,7 +285,7 @@ public:
/// Returns true if the Any is empty.
{
char buf[POCO_SMALL_OBJECT_SIZE] = { 0 };
return 0 == std::memcmp(_valueHolder.holder, buf, POCO_SMALL_OBJECT_SIZE);
return 0 == std::memcmp(_valueHolder.holder.h, buf, POCO_SMALL_OBJECT_SIZE);
}
const std::type_info & type() const
@@ -318,7 +328,7 @@ private:
{
if ((sizeof(Holder<ValueType>) <= POCO_SMALL_OBJECT_SIZE))
{
new ((ValueHolder*) pPlaceholder->holder) Holder(_held);
new ((ValueHolder*) pPlaceholder->holder.h) Holder(_held);
pPlaceholder->setLocal(true);
}
else
@@ -344,7 +354,7 @@ private:
{
if (sizeof(Holder<ValueType>) <= Placeholder<ValueType>::Size::value)
{
new (reinterpret_cast<ValueHolder*>(_valueHolder.holder)) Holder<ValueType>(value);
new (reinterpret_cast<ValueHolder*>(_valueHolder.holder.h)) Holder<ValueType>(value);
_valueHolder.setLocal(true);
}
else

View File

@@ -45,7 +45,7 @@
// Define to enable C++11 support
// #define POCO_ENABLE_CPP11
// #define POCO_ENABLE_CPP11
// Define to disable implicit linking
@@ -100,11 +100,17 @@
// candidates) will be auto-allocated on the stack in
// cases when value holder fits into POCO_SMALL_OBJECT_SIZE
// (see below).
//
// !!! NOTE: Any/Dynamic::Var SOO may 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,
// objects longer than this value will be alocated on the heap.
// objects larger than this value will be alocated on the heap,
// while those smaller will be placement new-ed into an
// internal buffer.
#if !defined(POCO_SMALL_OBJECT_SIZE) && !defined(POCO_NO_SOO)
#define POCO_SMALL_OBJECT_SIZE 32
#endif

View File

@@ -110,14 +110,10 @@ public:
Var(const T& val)
/// Creates the Var from the given value.
#ifdef POCO_NO_SOO
: _pHolder(new VarHolderImpl<T>(val)),
_pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
: _pHolder(new VarHolderImpl<T>(val))
{
}
#else
: _pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
construct(val);
}
@@ -135,10 +131,10 @@ public:
void swap(Var& other);
/// Swaps the content of the this Var with the other Var.
ConstIterator& begin() const;
ConstIterator begin() const;
/// Returns the const Var iterator.
ConstIterator& end() const;
ConstIterator end() const;
/// Returns the const Var iterator.
Iterator begin();
@@ -629,7 +625,7 @@ private:
{
if (sizeof(VarHolderImpl<ValueType>) <= Placeholder<ValueType>::Size::value)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<ValueType>(value);
new (reinterpret_cast<VarHolder*>(_placeholder.holder.h)) VarHolderImpl<ValueType>(value);
_placeholder.setLocal(true);
}
else
@@ -644,7 +640,7 @@ private:
std::string val(value);
if (sizeof(VarHolderImpl<std::string>) <= Placeholder<std::string>::Size::value)
{
new (reinterpret_cast<VarHolder*>(_placeholder.holder)) VarHolderImpl<std::string>(val);
new (reinterpret_cast<VarHolder*>(_placeholder.holder.h)) VarHolderImpl<std::string>(val);
_placeholder.setLocal(true);
}
else
@@ -676,9 +672,6 @@ private:
Placeholder<VarHolder> _placeholder;
#endif // POCO_NO_SOO
Iterator* _pBegin;
Iterator* _pEnd;
};
@@ -732,30 +725,28 @@ inline const std::type_info& Var::type() const
}
inline Var::ConstIterator& Var::begin() const
inline Var::ConstIterator Var::begin() const
{
if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
if (isEmpty()) return ConstIterator(const_cast<Var*>(this), true);
return *_pBegin;
return ConstIterator(const_cast<Var*>(this), false);
}
inline Var::ConstIterator& Var::end() const
inline Var::ConstIterator Var::end() const
{
return *_pEnd;
return ConstIterator(const_cast<Var*>(this), true);
}
inline Var::Iterator Var::begin()
{
if (isEmpty()) _pBegin->setPosition(Iterator::POSITION_END);
else if (*_pBegin == *_pEnd) _pBegin->setPosition(0);
if (isEmpty()) return Iterator(const_cast<Var*>(this), true);
return *_pBegin;
return Iterator(const_cast<Var*>(this), false);
}
inline Var::Iterator Var::end()
{
return *_pEnd;
return Iterator(this, true);
}

View File

@@ -286,9 +286,9 @@ protected:
poco_check_ptr (pVarHolder);
if ((sizeof(VarHolderImpl<T>) <= Placeholder<T>::Size::value))
{
new ((VarHolder*) pVarHolder->holder) VarHolderImpl<T>(val);
new ((VarHolder*) pVarHolder->holder.h) VarHolderImpl<T>(val);
pVarHolder->setLocal(true);
return (VarHolder*) pVarHolder->holder;
return (VarHolder*) pVarHolder->holder.h;
}
else
{

View File

@@ -47,26 +47,20 @@ namespace Poco {
namespace Dynamic {
Var::Var() :
Var::Var()
#ifdef POCO_NO_SOO
_pHolder(0),
: _pHolder(0)
#endif
_pBegin(new Iterator(this, true)),
_pEnd(new Iterator(this, true))
{
}
Var::Var(const char* pVal)
#ifdef POCO_NO_SOO
: _pHolder(new VarHolderImpl<std::string>(pVal)),
_pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
: _pHolder(new VarHolderImpl<std::string>(pVal))
{
}
#else
: _pBegin(new Iterator(this, false)),
_pEnd(new Iterator(this, true))
{
construct(std::string(pVal));
}
@@ -75,14 +69,10 @@ Var::Var(const char* pVal)
Var::Var(const Var& other)
#ifdef POCO_NO_SOO
: _pHolder(other._pHolder ? other._pHolder->clone() : 0),
_pBegin(new Iterator(*other._pBegin)),
_pEnd(new Iterator(*other._pEnd))
: _pHolder(other._pHolder ? other._pHolder->clone() : 0)
{
}
#else
: _pBegin(new Iterator(*other._pBegin)),
_pEnd(new Iterator(*other._pEnd))
{
if ((this != &other) && !other.isEmpty())
construct(other);