poco/Foundation/include/Poco/SmallObjectAllocator.h
2013-01-31 21:12:13 -06:00

252 lines
6.3 KiB
C++

//
// SmallObjectAllocator.h
//
// $Id: //poco/1.4/Foundation/include/Poco/SmallObjectAllocator.h#1 $
//
// Library: Foundation
// Package: Core
// Module: SmallObjectAllocator
//
// Definition of the SmallObjectAllocator template.
//
// Copyright (c) 2004-2006, 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.
//
#ifndef Foundation_SmallObjectAllocator_INCLUDED
#define Foundation_SmallObjectAllocator_INCLUDED
#include "Poco/Foundation.h"
#include "Poco/Types.h"
namespace Poco {
template <typename T, std::size_t S = sizeof(T)>
class SmallObjectAllocator
/// SmallObjectAllocator template is a lightweight wrapper implementing
/// small object allocation optimization idiom. Class is statically
/// parameterized on type created and the size threshold, which defaults
/// to the created object size; it follows that the default behavior is
/// use of automatically allocated memory (i.e. the value wrapped is
/// stored in the pre-allocated buffer). To enforce heap allocation,
/// specify S parameter to a value smaller than the size of the type
/// being instantiated.
///
/// The SmallObjectAllocator trade-off is the runtime check for memory
/// location where the value resides. The runtime check occurs at
/// construction/destruction as well as every value access. Value
/// access check can be alleviated by caching the value reference.
///
/// Usage example:
///
/// SmallObjectAllocator<int> s; // on the stack
/// SmallObjectAllocator<int, 1> h; // force heap alloc
/// int& i = s.get(); // no runtime performance penalty after this point
/// i = 5;
///
{
public:
SmallObjectAllocator()
{
if (isOnHeap()) _memory.ptr = new T();
else new (_memory.buf) T;
}
SmallObjectAllocator(const T& val)
{
if (isOnHeap()) _memory.ptr = new T(val);
else new (_memory.buf) T(val);
}
SmallObjectAllocator(const SmallObjectAllocator& other)
{
if (this != &other)
{
if (isOnHeap())
_memory.ptr = new T(*other._memory.ptr);
else
new (_memory.buf) T(*reinterpret_cast<const T*>(other._memory.buf));
}
}
~SmallObjectAllocator()
{
if (isOnHeap()) delete _memory.ptr;
else reinterpret_cast<T*>(_memory.buf)->~T();
}
SmallObjectAllocator& operator =(const SmallObjectAllocator& other)
{
if (this != &other)
{
if (isOnHeap())
_memory.ptr = new T(*other._memory.ptr);
else
new (_memory.buf) T(*reinterpret_cast<const T*>(other._memory.buf));
}
return *this;
}
T& get()
{
if (isOnHeap())
return *_memory.ptr;
else
return reinterpret_cast<T&>(*(_memory.buf));
}
const T& get() const
{
if (isOnHeap())
return *_memory.ptr;
else
return reinterpret_cast<const T&>(*_memory.buf);
}
bool isOnHeap() const
{
return sizeof(T) > S;
}
private:
union
{
unsigned char buf[S];
T* ptr;
} _memory;
};
template <>
class SmallObjectAllocator <char*>
/// SmallObjectAllocator char* specialization.
///
/// The treshold between auto and heap allocation
/// is controlled through POCO_SMALL_OBJECT_SIZE compile
/// time constant, which on 32 or 64 systems defaults
/// to 31 or 63 bytes respectively. This specialization
/// adds an extra byte to indicate the allocation strategy.
///
/// To summarize, e.g. POCO_SMALL_OBJECT_SIZE value of 7 will
/// take up at least 8 bytes of storage (for auto allocation)
/// with 6 bytes as the effective string length:
///
/// +---+---+---+---+---+---+---+---+
/// | c | c | c | c | c | c | 0 | f |
/// +---+---+---+---+---+---+---+---+
///
/// Legend:
/// c - character
/// 0 - terminating zero
/// f - allocation flag
///
{
public:
static const std::size_t Size = POCO_SMALL_OBJECT_SIZE;
SmallObjectAllocator(std::size_t sz)
{
_memory.buf[Size] = (sz > Size) ? 1 : 0;
if (_memory.buf[Size]) _memory.ptr = new char[sz + 1];
}
SmallObjectAllocator(const char* pCh, std::size_t sz)
{
allocateAndAssign(pCh, sz);
}
SmallObjectAllocator(const char* pCh)
{
allocateAndAssign(pCh, strlen(pCh));
}
~SmallObjectAllocator()
{
if (_memory.buf[Size]) delete _memory.ptr;
}
SmallObjectAllocator <char*>& operator = (const char* pCh)
{
allocateAndAssign(pCh, strlen(pCh));
return *this;
}
char* get()
{
if (_memory.buf[Size]) return _memory.ptr;
else return _memory.buf;
}
const char* get() const
{
if (_memory.buf[Size]) return _memory.ptr;
else return _memory.buf;
}
bool isOnHeap() const
{
return _memory.buf[Size] != 0;
}
private:
SmallObjectAllocator();
void allocateAndAssign(const char* pCh, std::size_t sz)
{
_memory.buf[Size] = (sz > Size) ? 1 : 0;
if (_memory.buf[Size])
{
_memory.ptr = new char[sz + 1];
_memory.ptr[sz] = '\0';
std::memcpy(_memory.ptr, pCh, sz);
}
else
{
_memory.buf[sz] = '\0';
std::memcpy(_memory.buf, pCh, sz);
}
}
union
{
char buf[Size + 1];
char* ptr;
} _memory;
};
typedef SmallObjectAllocator<char*> SmallStringAllocator;
} // namespace Poco
#endif // Foundation_SmallObjectAllocator_INCLUDED