AutoFreeAlloc

概览

AutoFreeAlloc是一个最袖珍的GC Allocator。主要针对于局部的复杂算法。为这些局部复杂算法提供内存管理能力,使得C++程序员也可以象GC语言的程序员一样,可以全力关注于业务逻辑本身,而不被繁琐的内存管理细节所困扰。

AutoFreeAlloc的实现细节,请参考《C++内存管理变革(2):最袖珍的垃圾回收器 - AutoFreeAlloc》。这个GC Allocator获得了很大的成功,被广泛应用到我们实际的项目中。 当然,AutoFreeAlloc也有其天然的缺陷,需要理解什么情况下可以用它,而什么情况下不能用它(请参阅《C++内存管理变革(3):另类内存管理 - AutoFreeAlloc典型应用》)。在不能用AutoFreeAlloc的情形下,你可以考虑用ScopeAlloc

规格

template <class _Policy>
class AutoFreeAllocT
{
public:
    typedef typename _Policy::allocator_type allocator_type;
 
    enum { MemBlockSize = _Policy::MemBlockSize };
    enum { HeaderSize = sizeof(void*) };
    enum { BlockSize = MemBlockSize - HeaderSize };
    enum { IsAutoFreeAllocator = 1 };
 
public:
    AutoFreeAllocT();
    explicit AutoFreeAllocT(_Alloc alloc);
    explicit AutoFreeAllocT(AutoFreeAllocT& owner);
 
    ~AutoFreeAllocT(); // 析构,将调用clear()清理内存
 
    void winx_call swap(AutoFreeAllocT& o); // 交换两个AutoFreeAlloc实例
 
    void winx_call clear(); // 清除由该类管理的所有对象(对象的析构亦被调用)
 
    template <class Type>
    void winx_call destroy(Type* obj); // 空操作
 
    template <class Type>
    Type* winx_call newArray(size_t count, Type* zero); // 创建数组
 
    template <class Type>
    void winx_call destroyArray(Type* array, size_t count); // 空操作
 
    void* winx_call allocate(size_t cb); // 申请内存
    void* winx_call allocate(size_t cb, DestructorType fn); // 申请内存,并指定析构函数
    void* winx_call allocate(size_t cb, int fnZero);
};
 
class StdAlloc
{
public:
    enum { MemBlockSize = MEMORY_BLOCK_SIZE };
    typedef DefaultStaticAlloc allocator_type;
};
 
typedef AutoFreeAllocT<StdAlloc> AutoFreeAlloc;

_Policy

  • AutoFreeAlloc所采用的策略。规格如下:
class _Policy
{
public:
    typedef XXX allocator_type;
    enum { MemBlockSize = XXX };
}

allocator_type

  • AutoFreeAlloc所基于的Allocator。该Allocator负责为AutoFreeAlloc提供MemBlock(大内存块)的分配1。其规格要求如下:
class Allocator
{
public:
    Allocator();
    Allocator(const Allocator& alloc); // 拷贝构造
 
    void* allocate(size_t cb); // 申请内存
    void deallocate(void* p); // 释放内存
 
    void swap(Allocator& alloc); // 交换两个Allocator实例
};

MemBlockSize

  • AutoFreeAlloc中的MemBlock大小,它是AutoFreeAlloc性能调配的重要参数。默认我们给了一个经验值:MEMORY_BLOCK_SIZE

构造函数

AutoFreeAllocT();
explicit AutoFreeAllocT(_Alloc alloc);
explicit AutoFreeAllocT(AutoFreeAllocT& owner);

alloc

  • 指出AutoFreeAlloc应该从那个alloc实例中分配MemBlock。请注意,AutoFreeAlloc并不直接使用该alloc,而是执行一次拷贝构造。这通常要求_Alloc是一个全局内存Allocator,或者是一个Allocator代理。详细参加上面对_Alloc的注解。

owner

  • 该AutoFreeAlloc的逻辑拥有者(Owner)。但是其实两者并无真正意义上的父子关系,新构造出来的AutoFreeAlloc实例只是用owner中的alloc成员拷贝构造了一份而已(从这个意义上来讲,两者更像是兄弟^_^)。

swap - 交换两个AutoFreeAlloc实例

void winx_call swap(AutoFreeAllocT& o);

o

  • 要交换的AutoFreeAlloc实例。

clear - 清除管理的所有对象

void winx_call clear(); // 清除由该类管理的所有对象(对象的析构亦被调用)

注意

  • 谨慎!该函数应在确保该AutoFreeAlloc所分配的所有对象都不再需要的情形下调用。

destroy - 空操作

template <class Type>
void winx_call destroy(Type* obj);
  • 该函数本意是释放一个对象。但是由于AutoFreeAlloc并不支持单独释放一个对象,故此该函数实际上只是一个空操作。

newArray - 创建数组

template <class Type>
Type* winx_call newArray(size_t count, Type* zero);
  • 该函数用于创建一个元素类型为Type的数组。但我们并不推荐直接使用它,而是应该用STD_NEW_ARRAY来完成这件事。

destroyArray - 空操作

template <class Type>
void winx_call destroyArray(Type* array, size_t count);
  • 该函数本意是释放一个数组。但是由于AutoFreeAlloc并不支持单独去释放某些对象,故此该函数实际上只是一个空操作。

allocate - 申请内存

void* winx_call allocate(size_t cb); // 申请内存
void* winx_call allocate(size_t cb, DestructorType fn); // 申请内存,并指定析构函数

cb

  • 要申请的内存大小。以字节数(byte)为单位。

fn

  • 回收该内存需要调用的函数。通常它是一个类的析构函数。当然你也可以将它用作给一个特殊的内存结构提供特定的回收函数。
  • 我们推荐析构函数只是一些乏味的内存释放(回收)操作。其实和[[[cn:GC]]语言一样,我们理论上并不需要有析构函数,如果一切内存都在GC Allocator掌握之中的话。但是在C++中这种想法并不现实:例如,我们假设用户在类A中使用std::vector,std::string等类。当一个类有了这些类的实例,哪怕用户没有写析构函数,但是一个隐含的析构被生成。如果我们只是释放类A的内存,而不执行其析构,那么内存泄漏就发生了。
void* winx_call allocate(size_t cb, int fnZero);
  • 这个函数其实只是一个优化函数。其功能等同于allocate(cb)。它在STD_NEW(alloc, Type)2时如果发现Type类没有析构函数3时被调用。

相关参考

使用样例

(todo)

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License