greenplumn CMemoryPool 源码
greenplumn CMemoryPool 代码
文件路径:/src/backend/gporca/libgpos/include/gpos/memory/CMemoryPool.h
//---------------------------------------------------------------------------
// Greenplum Database
// Copyright (C) 2008-2010 Greenplum Inc.
// Copyright (C) 2011 EMC Corp.
//
// @filename:
// CMemoryPool.h
//
// @doc:
// Abstraction of memory pool management. Memory pool types are derived
// from this class as drop-in replacements. This acts as an abstract class,
// concrete memory pools such as CMemoryPoolTracker and CMemoryPoolPalloc are
// derived from this.
// Some things to note:
// 1. When allocating memory, we have the mp pointer that we are allocating into.
// However, when deleting memory, we no longer have that pointer. How we free
// this memory is dependent on the memory pool used, which we get from the
// memory pool manager.
// 2. When deleting an array, we need to iterate through each element of the array.
// To calculate this, we calculate the length by calling UserSizeOfAlloc(). This
// is only done for allocations of type EatArray and thus we do not store the
// allocation length for non-array allocations.
//
//---------------------------------------------------------------------------
#ifndef GPOS_CMemoryPool_H
#define GPOS_CMemoryPool_H
#include "gpos/assert.h"
#include "gpos/common/CLink.h"
#include "gpos/common/CStackDescriptor.h"
#include "gpos/error/CException.h"
#include "gpos/types.h"
// 8-byte alignment
#define GPOS_MEM_ARCH (8)
#define GPOS_MEM_ALIGNED_SIZE(x) \
(GPOS_MEM_ARCH * (((x) / GPOS_MEM_ARCH) + ((x) % GPOS_MEM_ARCH ? 1 : 0)))
// padded size for a given data structure
#define GPOS_MEM_ALIGNED_STRUCT_SIZE(x) GPOS_MEM_ALIGNED_SIZE(GPOS_SIZEOF(x))
// sanity check: char and ulong always fits into the basic unit of alignment
GPOS_CPL_ASSERT(GPOS_MEM_ALIGNED_STRUCT_SIZE(gpos::CHAR) == GPOS_MEM_ARCH);
GPOS_CPL_ASSERT(GPOS_MEM_ALIGNED_STRUCT_SIZE(gpos::ULONG) == GPOS_MEM_ARCH);
// static pattern to init memory
#define GPOS_MEM_INIT_PATTERN_CHAR (0xCC)
// pattern used to mark deallocated memory, this must match
// GPOS_WIPED_MEM_PATTERN defined in CRefCount.h
#define GPOS_MEM_FREED_PATTERN_CHAR (0xCD)
// max allocation per request: 1GB
#define GPOS_MEM_ALLOC_MAX (0x40000000)
#define GPOS_MEM_OFFSET_POS(p, ullOffset) ((void *) ((BYTE *) (p) + ullOffset))
namespace gpos
{
// prototypes
class IMemoryVisitor;
//---------------------------------------------------------------------------
// @class:
// CMemoryPool
//
// @doc:
// Interface class for memory pool
//
//---------------------------------------------------------------------------
class CMemoryPool
{
// manager accesses internal functionality
friend class CMemoryPoolManager;
private:
// hash key is only set by pool manager
ULONG_PTR m_hash_key;
#ifdef GPOS_DEBUG
// stack where pool is created
CStackDescriptor m_stack_desc;
#endif // GPOS_DEBUG
// link structure to manage pools
SLink m_link;
protected:
// invalid memory pool key
static const ULONG_PTR m_invalid;
public:
enum EAllocationType
{
EatUnknown = 0x00,
EatSingleton = 0x7f,
EatArray = 0x7e
};
// dtor
virtual ~CMemoryPool() = default;
// prepare the memory pool to be deleted
virtual void TearDown() = 0;
// hash key accessor
virtual ULONG_PTR
GetHashKey() const
{
return m_hash_key;
}
// implementation of placement new with memory pool
virtual void *NewImpl(const ULONG bytes, const CHAR *file, const ULONG line,
CMemoryPool::EAllocationType eat) = 0;
// implementation of array-new with memory pool
template <typename T>
T *
NewArrayImpl(SIZE_T num_elements, const CHAR *filename, ULONG line)
{
T *array = static_cast<T *>(
NewImpl(sizeof(T) * num_elements, filename, line, EatArray));
for (SIZE_T idx = 0; idx < num_elements; ++idx)
{
try
{
new (array + idx) T();
}
catch (...)
{
// If any element's constructor throws, deconstruct
// previous objects and reclaim memory before rethrowing.
for (SIZE_T destroy_idx = idx - 1; destroy_idx < idx;
--destroy_idx)
{
array[destroy_idx].~T();
}
DeleteImpl(array, EatArray);
throw;
}
}
return array;
}
// return total allocated size
virtual ULLONG
TotalAllocatedSize() const
{
GPOS_ASSERT(!"not supported");
return 0;
}
// requested size of allocation
static ULONG UserSizeOfAlloc(const void *ptr);
// free allocation
static void DeleteImpl(void *ptr, EAllocationType eat);
#ifdef GPOS_DEBUG
// check if the memory pool keeps track of live objects
virtual BOOL
SupportsLiveObjectWalk() const
{
return false;
}
// walk the live objects, calling pVisitor.visit() for each one
virtual void
WalkLiveObjects(IMemoryVisitor *)
{
GPOS_ASSERT(!"not supported");
}
// dump memory pool to given stream
IOstream &OsPrint(IOstream &os);
// check if a memory pool is empty
virtual void AssertEmpty(IOstream &os);
#endif // GPOS_DEBUG
}; // class CMemoryPool
// Overloading placement variant of singleton new operator. Used to allocate
// arbitrary objects from an CMemoryPool. This does not affect the ordinary
// built-in 'new', and is used only when placement-new is invoked with the
// specific type signature defined below.
#ifdef GPOS_DEBUG
//---------------------------------------------------------------------------
// @function:
// CMemoryPool::operator <<
//
// @doc:
// Print function for memory pools
//
//---------------------------------------------------------------------------
inline IOstream &
operator<<(IOstream &os, CMemoryPool &mp)
{
return mp.OsPrint(os);
}
#endif // GPOS_DEBUG
namespace delete_detail
{
// All-static helper class. Base version deletes unqualified pointers / arrays.
template <typename T>
class CDeleter
{
public:
static void
Delete(T *object)
{
if (nullptr == object)
{
return;
}
// Invoke destructor, then free memory.
object->~T();
CMemoryPool::DeleteImpl(object, CMemoryPool::EatSingleton);
}
static void
DeleteArray(T *object_array)
{
if (nullptr == object_array)
{
return;
}
// Invoke destructor on each array element in reverse
// order from construction.
const SIZE_T num_elements =
CMemoryPool::UserSizeOfAlloc(object_array) / sizeof(T);
for (SIZE_T idx = num_elements - 1; idx < num_elements; --idx)
{
object_array[idx].~T();
}
// Free memory.
CMemoryPool::DeleteImpl(object_array, CMemoryPool::EatArray);
}
};
// Specialization for const-qualified types.
template <typename T>
class CDeleter<const T>
{
public:
static void
Delete(const T *object)
{
CDeleter<T>::Delete(const_cast<T *>(object));
}
static void
DeleteArray(const T *object_array)
{
CDeleter<T>::DeleteArray(const_cast<T *>(object_array));
}
};
} // namespace delete_detail
} // namespace gpos
// Overloading placement variant of singleton new operator. Used to allocate
// arbitrary objects from an CMemoryPool. This does not affect the ordinary
// built-in 'new', and is used only when placement-new is invoked with the
// specific type signature defined below.
inline void *
operator new(gpos::SIZE_T size, gpos::CMemoryPool *mp,
const gpos::CHAR *filename, gpos::ULONG line)
{
return mp->NewImpl(size, filename, line, gpos::CMemoryPool::EatSingleton);
}
// Corresponding placement variant of delete operator. Note that, for delete
// statements in general, the compiler can not determine which overloaded
// version of new was used to allocate memory originally, and the global
// non-placement version is used. This placement version of 'delete' is used
// *only* when a constructor throws an exception, and the version of 'new' is
// known to be the one declared above.
inline void
operator delete(void *ptr, gpos::CMemoryPool *, const gpos::CHAR *, gpos::ULONG)
{
// Reclaim memory after constructor throws exception.
gpos::CMemoryPool::DeleteImpl(ptr, gpos::CMemoryPool::EatSingleton);
}
// Placement new-style macro to do 'new' with a memory pool. Anything allocated
// with this *must* be deleted by GPOS_DELETE, *not* the ordinary delete
// operator.
#define GPOS_NEW(mp) new (mp, __FILE__, __LINE__)
// Replacement for array-new. Conceptually equivalent to
// 'new(mp) datatype[count]'. Any arrays allocated with this *must* be deleted
// by GPOS_DELETE_ARRAY, *not* the ordinary delete[] operator.
//
// NOTE: Unlike singleton new, we do not overload the built-in new operator for
// arrays, because when we do so the C++ compiler adds its own book-keeping
// information to the allocation in a non-portable way such that we can not
// recover GPOS' own book-keeping information reliably.
#define GPOS_NEW_ARRAY(mp, datatype, count) \
mp->NewArrayImpl<datatype>(count, __FILE__, __LINE__)
// Delete a singleton object allocated by GPOS_NEW().
template <typename T>
void
GPOS_DELETE(T *object)
{
::gpos::delete_detail::CDeleter<T>::Delete(object);
}
// Delete an array allocated by GPOS_NEW_ARRAY().
template <typename T>
void
GPOS_DELETE_ARRAY(T *object_array)
{
::gpos::delete_detail::CDeleter<T>::DeleteArray(object_array);
}
#endif // !GPOS_CMemoryPool_H
// EOF
相关信息
相关文章
greenplumn CMemoryPoolManager 源码
greenplumn CMemoryPoolStatistics 源码
greenplumn CMemoryPoolTracker 源码
0
赞
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦