模板类的自动内存池功能

时间:2017-01-04 11:10:43

标签: c++ c++11 templates gcc memory-management

story的延续。

考虑安全软件,其中不允许使用碎片进行动态分配。仅当class explicity定义operator deletenew以避免碎片时才允许动态分配。

现在,我们有机会针对我们想要获得的任何类优化运算符deletetemplate<class T, unsigned size> class MemoryPool { private: struct Pool { bool allocated __attribute__ ((aligned (sizeof(void*)))); uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*)))); }; static std::array<uint8_t[sizeof(Pool)], size> memoryPool; public: void* operator new(std::size_t) noexcept { T* ret = nullptr; for(auto it = memoryPool.begin(); it != memoryPool.end(); ++it) { /* ... */ } return ret; } void operator delete(void* ptr) noexcept { for(auto it = memoryPool.begin(); it != memoryPool.end(); ++it) { /* ... */ } } }; 的显式定义。乍一看,任何类都可以继承的模板类是最简单,最清晰的方法,可供最终用户使用。

class Interface
{/*...*/};

class Foo : public Interface,  MemoryPool<Foo, 8>
{/*...*/};

class Bar : public Interface
{/*...*/};

如果这是一个童话故事,那么使用MemoryPool宣传课程会很好。

Foo* foo = new Foo(); // goes to dedicated memory pool
Bar* bar = new Bar(); // fails on build

对象声明:

static std::array<uint8_t[sizeof(Pool)], size> memoryPool;

但即使Foo是静态的并且会超出类,因此它不会改变类的大小,编译器会抱怨Foo不完整且不能推断出大小src/metal/dynamic.hpp:14:24: error: invalid application of 'sizeof' to incomplete type 'Foo' uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));

{{1}}

是否可以解决此“不完整类型”错误?

或者我应该完全重新设计解决方案?

1 个答案:

答案 0 :(得分:2)

问题是Foo在实例化MemoryPool时还不是一个完整的类型。

clang's error message非常具体:

main.cpp:10:24: error: invalid application of 'sizeof' to an incomplete type 'Foo'
        uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));
                       ^~~~~~~~~
main.cpp:13:31: note: in instantiation of member class 'MemoryPool<Foo, 8>::Pool' requested here

    static std::array<uint8_t[sizeof(Pool)], size> memoryPool;
                              ^
main.cpp:35:20: note: in instantiation of template class 'MemoryPool<Foo, 8>' requested here
class Foo : public MemoryPool<Foo, 8>
                   ^
main.cpp:35:7: note: definition of 'Foo' is not complete until the closing '}'
class Foo : public MemoryPool<Foo, 8>
  ^

您可以通过延迟应用sizeof来解决此问题,直到Foo为完整类型。

这可以通过静态成员函数访问memoryPool来完成:

template<class T, unsigned size>
class MemoryPool
{
private:
    struct Pool
    {
        bool    allocated         __attribute__ ((aligned (sizeof(void*))));
        uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));
    };

    template <typename P>
    static std::array<uint8_t[sizeof(P)], size>& getPool()
    {
        static std::array<uint8_t[sizeof(P)], size> memoryPool;
        return memoryPool;
    }
public:
    void* operator new(std::size_t) noexcept
    {
        T* ret = nullptr;
        for(auto it = getPool<Pool>().begin(); it != getPool<Pool>().end(); ++it)
        {
           /* ... */
        } 
        return ret;
    }
};

<强> live example

C ++ 14允许稍微简单的实现:

template<class T, unsigned size>
class MemoryPool
{
private:
    struct Pool
    {
        bool    allocated         __attribute__ ((aligned (sizeof(void*))));
        uint8_t memory[sizeof(T)] __attribute__ ((aligned (sizeof(void*))));
    };

    static auto& getPool()
    {
        static std::array<uint8_t[sizeof(Pool)], size> memoryPool;
        return memoryPool;
    }
public:
    void* operator new(std::size_t) noexcept
    {
        T* ret = nullptr;
        for(auto it = getPool().begin(); it != getPool().end(); ++it)
        {
           /* ... */
        } 
        return ret;
    }
};

<强> live example