Created
February 10, 2017 07:00
-
-
Save PixelClear/bd482ec691fb19548a392570947b6721 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<new> | |
#include<cassert> | |
using std::cout; | |
using std::cin; | |
using std::endl; | |
namespace Numbers | |
{ | |
/* --------------------------------------------Memory Pool--------------------------------------*/ | |
template<class T> | |
class MemoryPool | |
{ | |
private: | |
//Using const that #defines | |
static const int BLOCK_SIZE; | |
//Wants only class wide vopy | |
static T *head; | |
static T *newBlock; | |
public: | |
MemoryPool(); | |
void * alloc(size_t size); | |
void free_(void* p, size_t size); | |
~MemoryPool(); | |
}; | |
//Static definations | |
template<class T> | |
const int Numbers::MemoryPool<T>::BLOCK_SIZE = 512; | |
template<class T> | |
T* Numbers::MemoryPool<T>::head; | |
template<class T> | |
T* Numbers::MemoryPool<T>::newBlock; | |
template<class T> | |
Numbers::MemoryPool<T>::MemoryPool() | |
{ | |
} | |
template<class T> | |
Numbers::MemoryPool<T>::~MemoryPool() | |
{ | |
::operator delete(newBlock); | |
} | |
template<class T> | |
void* Numbers::MemoryPool<T>::alloc(size_t size) | |
{ | |
/*If derived class doesnt implement new and calls new here we handle case | |
This case also handles when size is zero as objects size cant be zero | |
in case of zero size we will fall back to global new. So we are not flexible | |
but we are fast*/ | |
if(size != sizeof(T)) | |
return ::operator new(size); // Let the global new handle the case | |
T *p = head; | |
if(p != NULL) | |
head = p->next; | |
else | |
{ | |
/*Allocate huge block and make list out of it*/ | |
if(newBlock == NULL) | |
newBlock = static_cast<T*>(::operator new(BLOCK_SIZE * sizeof(T))); | |
for(int i = 1; i < BLOCK_SIZE-1; i++) | |
newBlock[i].next = & newBlock[i+1]; | |
newBlock[BLOCK_SIZE-1].next = NULL; | |
p = newBlock; // return 0th block | |
head = &newBlock[1]; // head points to 1s element now | |
} | |
return p; | |
} | |
template <class T> | |
void Numbers::MemoryPool<T>::free_(void* ptr, size_t size) | |
{ | |
if(ptr == 0) // handle case with deleting null pointer | |
return; | |
if(size != sizeof(Integer)) | |
{ | |
::operator delete(ptr); | |
return; | |
} | |
T* freeBlock = static_cast<T*>(ptr); | |
freeBlock->next = head; | |
head = freeBlock; | |
} | |
/* --------------------------------------------Memory Pool Ends--------------------------------------*/ | |
class Integer | |
{ | |
public : | |
Integer(){} | |
~Integer(){ | |
cout << "Inside ~Integer()"<<endl; | |
} | |
static void * operator new(size_t size); | |
static void operator delete(void *p, size_t size); | |
struct | |
{ | |
int data; | |
Integer* next; | |
}; | |
}; | |
//Memory Pool is in namespace | |
Numbers::MemoryPool<Numbers::Integer> memPool; | |
/*We are based on assumption on builing blocks because we know size request we will get | |
will be equal to Integer class so we skip lot of book keeping, memory fragmentation and | |
all steps so this version will be faster that global new*/ | |
inline void* Numbers::Integer::operator new(size_t size) | |
{ | |
return memPool.alloc(size); | |
} | |
/*Delete will recieve block of memory if it is of size of Integer | |
we will add this block to head of list*/ | |
inline void Numbers::Integer::operator delete(void* ptr, size_t size) | |
{ | |
memPool.free_(ptr,size); | |
} | |
}; | |
int main() | |
{ | |
Numbers::Integer *i1 = new Numbers::Integer; | |
i1->data = 10; | |
Numbers::Integer *i2 = new Numbers::Integer; | |
i2->data = 20; | |
delete i1; | |
delete i2; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment