My favorites | Sign in
Project Home Wiki Issues Source
READ-ONLY: This project has been archived. For more information see this post.
Project Information
Members
//Define.h

#ifndef _MEMORYPOOL_DEFINE_H_
#define _MEMORYPOOL_DEFINE_H_

namespace MemoryPool
{
;

typedef unsigned char byte;
typedef unsigned int uint;


}; // namespace MemoryPool

#endif _MEMORYPOOL_DEFINE_H_





=======================================================================================

#include "Define.h"

namespace MemoryPool
{
;

class Node
{
public:
    Node()
    :prev_(NULL)
    ,next_(NULL)
    {
    }
    virtual ~Node()
    {
        prev_ = NULL;
        next_ = NULL;
    }
    Node* Next()
    {
        return next_;
    }
    Node* Prev()
    {
        return prev_;
    }
    void Attach(Node* node)
    {
        node->prev_ = this;
        node->next_ = next_;
        next_ = node;
    }
private:
    Node* next_;
    Node* prev_;
};



=======================================================================================

                       | <----------- allocated memory ---------> |
                ----------------------------------------------------------
 PieceBlock     | head |  piece 1 |  piece 2 | piece 3 | .....    | tail  |
                ----------------------------------------------------------



class PieceBlock : public Node
{
public:
    PieceBlock(uint block_id);
    virtual ~PieceBlock();
    void* get_piece(uint index, uint piece_size, uint piece_count);
    uint GetID()
    {
        return id_;
    }
private:
    void* piece_;
    uint id_;
};

PieceBlock::PieceBlock(uint block_id)
:id_(block_id)
,piece_(NULL)
{
}

PieceBlock::~PieceBlock()
{
    if (piece_)
    {
        free(piece_);
        piece_ = NULL;
    }
}

void* PieceBlock::get_piece(uint index, uint piece_size, uint piece_count)
{
    if (index >= piece_count)
        return NULL;

    if (piece_ == NULL)
    {
        uint block_size = piece_size * piece_count;
        piece_ = malloc(block_size);
        assert(piece_);
        memset(piece_, 0, block_size);
    }

    byte* position = (byte*)piece_;
    position += index * piece_size;
    return position;
}


=======================================================================================



          PieceBlock -> PieceBlock -> ... ->PieceBlock -> NULL
          head                              tail 


class Container
{
public:
    Container(uint piece_size, uint piece_count);
    virtual ~Container();
    void ReSize(uint piece_count);

protected:
    void* At(uint index);

private:
    PieceBlock* head_;
    PieceBlock* tail_;
    PieceBlock* position_;
    uint piece_size_;
    uint piece_count_;
};

Container::Container(uint piece_size, uint piece_count)
:piece_size_(piece_size)
,piece_count_(piece_count)
,head_(NULL)
,tail_(NULL)
,position_(NULL)
{
    assert(piece_count_);
    assert(piece_size_);
}

Container::~Container()
{
    Node* node = head_;
    while (node)
    {
        Node* temp = node;
        node = node->Next();
        delete temp;
    }
}

void Container::ReSize(uint piece_count)
{
    assert(piece_count);
    if (piece_count_ == piece_count)
        return;

    piece_count_ = piece_count;
    Node* node = head_;
    while (node)
    {
        Node* temp = node;
        node = node->Next();
        delete temp;
    }

    head_ = NULL;
    tail_ = NULL;
    position_ = NULL;
}

void* Container::At(uint index)
{
    assert(piece_count_);
    uint block_index = index / piece_count_;

    if (head_ == NULL)
    {
        if (block_index != 0)
        {
            assert(0);
            return NULL;
        }

        head_ = new PieceBlock(0);
        position_ = head_;
        tail_ = head_;
    }

    if (position_->GetID() != block_index)
    {
        if (block_index == tail_->GetID())
        {
            position_ = tail_;
        }
        else if (block_index < tail_->GetID())
        {
            Node* node = head_;
            while (node)
            {
                if (((PieceBlock*)node)->GetID() == block_index)
                {
                    position_ = (PieceBlock*)node;
                    break;
                }
                node = node->Next();
            }
        }
        else
        {
            if (block_index == (tail_->GetID() + 1))
            {
                PieceBlock* next = new PieceBlock(block_index);
                assert(next);
                if (next)
                {
                    tail_->Attach(next);
                    tail_ = next;
                    position_ = next;
                }
            }
            else
            {
                assert(0);
                return NULL;
            }
        }
    }

    uint piece_index = index % piece_count_;
    return position_->get_piece(piece_index, piece_size_, piece_count_);
}



=======================================================================================



class Allocator : public Container
{
public:
    Allocator(uint piece_size, uint piece_count);
    virtual ~Allocator();
    void* Pop();
private:
    uint piece_index_;
};

Allocator::Allocator(uint piece_size, uint piece_count)
: Container(piece_size, piece_count)
, piece_index_(0)
{
}

Allocator::~Allocator()
{
}

void* Allocator::Pop()
{
    void* piece = At(piece_index_);
    if (piece)
    {
        ++piece_index_;
        return piece;
    }
    return NULL;
}



=======================================================================================



class Repository : public Container
{
public:
    Repository(uint piece_count);
    virtual ~Repository();

    void* Pop();
    void Push(void* ptr);

private:
    uint piece_index_;
};

Repository::Repository(uint piece_count)
: Container(sizeof(void *), piece_count)
, piece_index_(0)
{
}

Repository::~Repository()
{
}

void* Repository::Pop()
{
    if (piece_index_ <= 0)
        return NULL;

    uint idx = piece_index_ - 1;
    void** piece = (void**)At(idx);
    if (piece)
    {
        piece_index_ = idx;
        return *piece;
    }
    return NULL;
}

void Repository::Push(void* ptr)
{
    void** piece = (void**)At(piece_index_);
    if (piece)
    {
        *piece = ptr;
        ++piece_index_;
    }
}

}; // namespace MemoryPool

#endif _MEMORYPOOL_CONTAINER_H_




=======================================================================================


#ifndef _MEMORYPOOL_MEMORYPOOL_H_
#define _MEMORYPOOL_MEMORYPOOL_H_

#include <new>
#include <assert.h>
#include "./Define.h"
#include "./Container.h"

namespace MemoryPool
{
;

class Destroyer
{
public:
    Destroyer()
    {
    }
    virtual ~Destroyer()
    {
    }
    virtual void Destroy(void* ptr, void* object) = 0;
};
        


    -----------------------------------------------------
   | Destroyer * | piece * | Destroyer * | piece * | ....
    -----------------------------------------------------


template <class T>
class MemoryPool : public Destroyer
{
private:
    enum { default_piece_count = 8, };
public:
    static MemoryPool<T>* Instance()
    {
        static MemoryPool<T> static_pool;
        return &static_pool;
    }

    MemoryPool()
    : allocator_(sizeof(T) + sizeof(Destroyer*), default_piece_count)
    , repository_(default_piece_count/2)
    {
    }

    virtual ~MemoryPool()
    {
    }

    void ReSize(uint piece_count)
    {
        allocator_.ReSize(piece_count);
        repository_.ReSize(piece_count/2);
    }

    T* Create()
    {
        Destroyer** temp = (Destroyer**)repository_.Pop();
        if (temp == NULL)
        {
            temp = (Destroyer**)allocator_.Pop();
            if (temp == NULL)
                return NULL;
        }

        *temp = this;
        T* object = (T*)(temp + 1);

        // 생성자 호출.
        new(object) T();
        return object;
    }

    virtual void Destroy(void* ptr, void* object)
    {
        assert(ptr);
        assert(object);
        if (ptr && object)
        {
            // 소멸자 호출.
            T* temp = (T*)object;
            temp->T::~T();
            repository_.Push(ptr);
        }
    }

private:
    Allocator allocator_;
    Repository repository_;
};


void DeleteMemory(void* ptr)
{
    assert(ptr);
    Destroyer** temp = (Destroyer**)ptr;
    Destroyer* owner = *(temp - 1);
    if (owner == NULL)
    {
        //이중 삭제
        assert(0);
    }
    else
    {
        owner->Destroy(temp - 1, ptr);
        *(temp - 1) = NULL;
    }
}

}; // namespace MemoryPool


#define NkReSize(type_, n)  MemoryPool::MemoryPool<type_>::Instance()->ReSize(n);
#define NkNew(type_)        MemoryPool::MemoryPool<type_>::Instance()->Create();
#define NkDelete(ptr_)      MemoryPool::DeleteMemory(ptr_);


#endif _MEMORYPOOL_MEMORYPOOL_H_




=======================================================================================

#include <stdio.h>
#include <Windows.h>
#include "../SourceFile/MemoryPool/MemoryPool.h"

typedef unsigned int uint;

class A
{
public:
    A()
    {
    }
    virtual ~A()
    {
    }

    int a;
    int b;
    int c;
};

class B : public A
{
public:
    B()
    {
    }
    virtual ~B()
    {
    }
    int d;
    int e;
};


int main()
{
    const uint cnt = 100000;
    A* ar[cnt] = {0,};

    NkReSize(B, 100);

    do
    {
        {
            DWORD start = ::GetTickCount();
            for (uint i = 0 ; i < cnt ; ++i)
            {
                A* b = new B();
                ar[i] = b;
            }
            DWORD delta = ::GetTickCount() - start;

            DWORD start2 = ::GetTickCount();
            for (uint j = 0 ; j < cnt ; ++j)
            {
                delete ar[j];
            }
            DWORD delta2 = ::GetTickCount() - start2;

            printf("new : %d, delete : %d\r\n", delta, delta2);

        }

        {
            DWORD start = ::GetTickCount();
            for (uint i = 0 ; i < cnt ; ++i)
            {
                A* b = NkNew(B);
                ar[i] = b;
            }
            DWORD delta = ::GetTickCount() - start;


            DWORD start2 = ::GetTickCount();
            for (uint j = 0 ; j < cnt ; ++j)
            {
                NkDelete(ar[j]);
            }

            DWORD delta2 = ::GetTickCount() - start2;

            printf("nk new : %d, delete : %d\r\n", delta, delta2);
        }
    }
    while (getchar());

    return 0;
}

result.......not bad...

Powered by Google Project Hosting