greenplumn CRefCount 代码
文件路径:/src/backend/gporca/libgpos/include/gpos/common/CRefCount.h
/---------------------------------------------------------------------------
/ Greenplum Database
/ Copyright (C) 2008 Greenplum, Inc.
/
/ @filename:
/ CRefCount.h
/
/ @doc:
/ Base class for reference counting in the optimizer;
/ Ref-counting is single-threaded only;
/ Enforces allocation on the heap, i.e. no deletion unless the
/ count has really dropped to zero
/---------------------------------------------------------------------------
#ifndef GPOS_CRefCount_H
#define GPOS_CRefCount_H
#include "gpos/assert.h"
#include "gpos/common/CHeapObject.h"
#include "gpos/error/CException.h"
#include "gpos/task/ITask.h"
#include "gpos/types.h"
#include "gpos/utils.h"
/ pattern used to mark deallocated memory, this must match
/ GPOS_MEM_FREED_PATTERN_CHAR in CMemoryPool.h
#define GPOS_WIPED_MEM_PATTERN 0xCdCdCdCdCdCdCdCd
namespace gpos
{
/---------------------------------------------------------------------------
/ @class:
/ CRefCount
/
/ @doc:
/ Basic reference counting
/
/---------------------------------------------------------------------------
class CRefCount : public CHeapObject
{
private:
/ reference counter -- first in class to be in sync with Check()
ULONG_PTR m_refs{1};
#ifdef GPOS_DEBUG
/ sanity check to detect deleted memory
void
Check() const
{
/ assert that first member of class has not been wiped
GPOS_ASSERT(m_refs != GPOS_WIPED_MEM_PATTERN);
}
#endif / GPOS_DEBUG
public:
CRefCount(const CRefCount &) = delete;
/ ctor
CRefCount() = default;
/ FIXME: should mark this noexcept in non-assert builds
/ dtor
virtual ~CRefCount() noexcept(false)
{
/ enforce strict ref-counting unless we're in a pending exception,
/ e.g., a ctor has thrown
GPOS_ASSERT(nullptr == ITask::Self() ||
ITask::Self()->HasPendingExceptions() || 0 == m_refs);
}
/ return ref-count
ULONG_PTR
RefCount() const
{
return m_refs;
}
/ return true if calling object's destructor is allowed
virtual BOOL
Deletable() const
{
return true;
}
/ count up
void
AddRef()
{
#ifdef GPOS_DEBUG
Check();
#endif / GPOS_DEBUG
m_refs++;
}
/ count down
void
Release()
{
#ifdef GPOS_DEBUG
Check();
#endif / GPOS_DEBUG
m_refs--;
if (0 == m_refs)
{
if (!Deletable())
{
/ restore ref-count
AddRef();
/ deletion is not allowed
GPOS_RAISE(CException::ExmaSystem,
CException::ExmiInvalidDeletion);
}
GPOS_DELETE(this);
}
}
/ safe version of Release -- handles NULL pointers
static void
SafeRelease(CRefCount *rc)
{
if (nullptr != rc)
{
rc->Release();
}
}
}; / class CRefCount
} / namespace gpos
#endif / !GPOS_CRefCount_H
/ EOF