Skip to content

Instantly share code, notes, and snippets.

@mshabunin
Created December 30, 2019 22:40
Show Gist options
  • Save mshabunin/cb1e5d57c543d19ba8cba630e31fef58 to your computer and use it in GitHub Desktop.
Save mshabunin/cb1e5d57c543d19ba8cba630e31fef58 to your computer and use it in GitHub Desktop.
Memory pool with two modes: safe and fast
#include <cstddef>
#include <iostream>
#include <list>
// #define SAFE
using namespace std;
class Pool
{
// interface
class IBlock
{
public:
virtual ~IBlock() {}
virtual void * commit(void *) = 0;
virtual size_t getSize() const = 0;
};
// implementation
template <typename T>
class SafeBlock : public IBlock
{
public:
SafeBlock(T *&ptr_, size_t sz_) : ptr(ptr_)
{
cout << "One allocate " << sizeof(ptr) * sz_ << endl;
ptr = new T[sz_];
}
~SafeBlock()
{
delete[] ptr;
ptr = 0;
}
void * commit(void *) override { return 0; }
size_t getSize() const override { return 0; }
private:
T *&ptr;
};
// implementation
template <typename T>
class FastBlock : public IBlock
{
public:
FastBlock(T *&ptr_, size_t sz_) : ptr(ptr_), sz(sz_) {}
~FastBlock() {}
void *commit(void * buf) override
{
const size_t d = (unsigned long long)buf % sizeof(T);
if (d != 0)
{
cout << "Align pointer: " << buf << " -> ";
buf = (void*)((unsigned long long)buf + (sizeof(T) - d));
cout << buf << endl;
}
cout << "Use pointer: " << buf << endl;
ptr = (T*)buf;
buf = (void*)((T*)buf + sz);
return buf;
}
size_t getSize() const override { return sizeof(T) * sz; }
private:
T *&ptr;
size_t sz;
};
public:
Pool(bool safe_ = true) : safe(safe_), buf(0) {}
~Pool()
{
for(IBlock * b : blocks)
{
delete b;
}
if (buf)
{
cout << "Cleanup buf" << endl;
delete[] buf;
}
}
template <typename T>
void allocate(T*&ptr, size_t num)
{
if (!safe)
blocks.push_front(new FastBlock<T>(ptr, num));
else
blocks.push_front(new SafeBlock<T>(ptr, num));
}
void commit()
{
if (!safe)
{
size_t totalSize = 0; // bytes
for(IBlock * b : blocks)
{
totalSize += b->getSize() + 64; // alignment
}
cout << "Single allocate: " << totalSize << " bytes" << endl;
buf = new char[totalSize];
char *ptr = buf;
for(IBlock * b : blocks)
{
ptr = (char*)b->commit((void*)ptr);
}
}
}
private:
bool safe;
list<IBlock*> blocks;
char * buf;
};
void test(bool s)
{
char * u = 0;
int * a = 0;
double * b = 0;
cout << a << ", " << b << ", " << (void*)u << endl;
{
Pool p(s);
cout << "Allocate" << endl;
p.allocate<int>(a, 10);
p.allocate(u, 3);
p.allocate<double>(b, 20);
cout << a << ", " << b << ", " << (void*)u << endl;
cout << "Commit" << endl;
p.commit();
cout << a << ", " << b << ", " << (void*)u << endl;
}
cout << "Cleanup" << endl;
cout << a << ", " << b << ", " << (void*)u << endl;
}
int main()
{
cout << "==========" << endl;
test(true);
cout << "==========" << endl;
test(false);
cout << "==========" << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment