daily pastebin goal
92%
SHARE
TWEET

Untitled

a guest Jun 19th, 2017 45 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //StaticBuffer.h
  2.  
  3. //This file provides a class which allocates memory from a preallocated heap, in as quick a manner as possible.
  4. //Essentially, it provides a second stack for the program, one which never gets deallocated.
  5. //Usage: StaticMemoryAllocator::allocate(size_t bytes) returns a safely aligned void*
  6.  
  7. #ifndef PlaneGC_StaticBuffer_h
  8. #define PlaneGC_StaticBuffer_h
  9.  
  10. #include "Allocators.h"
  11.  
  12. namespace PlaneGC {
  13.  
  14. class StaticBuffer {
  15. public:
  16.     static const size_t blocksize= 0x10000; //How many bytes it will allocate at a time. It is also the max bytes it can allocate per request
  17.  
  18.     template<typename T> class stl_wrapper {
  19.     public:
  20.         typedef T value_type;
  21.         typedef size_t size_type;
  22.         typedef ptrdiff_t difference_type;
  23.         typedef T* pointer;
  24.         typedef const T* const_pointer;
  25.         typedef T& reference;
  26.         typedef const T& const_reference;
  27.  
  28.         stl_wrapper() { };
  29.         stl_wrapper(const stl_wrapper&) { };
  30.         template <class U> stl_wrapper(const stl_wrapper<U>&) { };
  31.  
  32.         size_t max_size() const { return max((size_t)1, blocksize / sizeof(T)); };
  33.  
  34.         template<class U> struct rebind { typedef stl_wrapper<U> other; };
  35.         pointer address(reference r) { return &r; }
  36.         const_pointer address(const_reference r) { return &r; }
  37.  
  38.         pointer allocate(size_type n, const void* hint= 0) { return (T*)StaticBuffer::allocate(n*sizeof(T)); };
  39.         void deallocate(pointer p, size_type n) { StaticBuffer::deallocate(p, n*sizeof(T)); };
  40.  
  41.         void construct(pointer p, const T& val) { new(p) T(val); };
  42.         void destroy(pointer p) { p->~T(); };
  43.     };
  44.  
  45. private:
  46.     class Block {
  47.     private:
  48.         Block(Block* previous_, uint bytes) {
  49.             previous= 0;
  50.             next= 0;
  51.             InsertAfter(previous_);
  52.             remaining= bytes;
  53.             head= (byte*)this + GetPaddedTotal(sizeof(*this));
  54.         };
  55.         ~Block() { RemoveLinks(); };
  56.     public:
  57.         static Block* CreateBlock(size_t minimum= StaticBuffer::blocksize) {
  58.             size_t size= max(minimum, StaticBuffer::blocksize);
  59.             return new(new byte[GetPaddedTotal(sizeof(Block)) + size]) Block(StaticBuffer::head(), size);
  60.         };
  61.         static void DestroyBlock(Block* block) {
  62.             if(!block) return;
  63.             block->~Block();
  64.             delete[] (byte*) block;
  65.         };;
  66.     private:
  67.         void InsertAfter(Block* previous_) {
  68.             if(previous_ == this) return;
  69.             RemoveLinks();
  70.             if(previous= previous_) {
  71.                 if(next= previous->next) next->previous= this;
  72.                 previous->next= this;
  73.             }
  74.         };
  75.         void RemoveLinks() {
  76.             if(StaticBuffer::head() == this) StaticBuffer::head()= next ? next : previous;
  77.             if(StaticBuffer::root() == this) StaticBuffer::root()= previous ? previous : next;
  78.             if(previous) previous->next= next;
  79.             if(next) next->previous= previous;
  80.         };
  81.         void SortIntoList() {
  82.             if(!previous) return;
  83.             //Moving this block to a position in the linked list where it will be sorted by bytesremaining
  84.             Block* current= previous;
  85.             while((current->remaining > remaining) && (current->previous)) {
  86.                 current= current->previous;
  87.             }
  88.             InsertAfter(current);
  89.         };
  90.  
  91.     public:
  92.         void* allocate(size_t bytes) {
  93.             assert(this == StaticBuffer::head());
  94.             if(remaining >= bytes) {
  95.                 void* result= head;
  96.                 head += bytes;
  97.                 remaining -= bytes;
  98.                 return result;
  99.             }else{
  100.                 Block* current= previous;
  101.                 while(current->previous && (current->remaining >= bytes)) {
  102.                     current= current->previous;
  103.                 }
  104.                 if(current->next && (current->next->remaining >= bytes)) {
  105.                     //found the block with the least free space which can take this request
  106.                     current= current->next;
  107.                     current->InsertAfter(this);
  108.                 }else{
  109.                     //no existing block had enough bytes
  110.                     current= CreateBlock(bytes);
  111.                 }
  112.                 StaticBuffer::head()= current;
  113.                 SortIntoList();
  114.                 return next->allocate(bytes);
  115.             }
  116.         };
  117.  
  118.     private:
  119.         Block* previous;
  120.         Block* next;
  121.         byte* head;
  122.         size_t remaining;
  123.     };
  124.  
  125. public:
  126.     StaticBuffer() {
  127.         inc();
  128.     };
  129.  
  130.     ~StaticBuffer() {
  131.         dec();
  132.     };
  133.  
  134.     static void inc() { ++reference_count(); };
  135.     static void dec() {
  136.         if(!(--reference_count())) {
  137.             lock();
  138.             while(root()) Block::DestroyBlock(root());
  139.             unlock();
  140.         }
  141.     };
  142.  
  143.     static void* allocate(size_t bytes) {
  144.         lock();
  145.         void* v= head()->allocate(bytes);
  146.         if(v) {
  147.             ++allocated_count();
  148.             allocated_bytes() += bytes;
  149.         }
  150.         unlock();
  151.  
  152.         return v;
  153.     };
  154.  
  155.     static void deallocate(void* memory, size_t bytes) {
  156.         deallocated_count() += bytes;
  157.     };
  158.  
  159.     static size_t& reference_count() { static size_t v= 0; return v; };
  160.     static size_t& allocated_count() { static size_t v= 0; return v; };
  161.     static size_t& deallocated_count() { static size_t v= 0; return v; };
  162.     static size_t& allocated_bytes() { static size_t v= 0; return v; };
  163.  
  164. private:
  165.     static Block*& root() { static Block* v= Block::CreateBlock(); return v; };
  166.     static Block*& head() { static Block* v= root(); return v; };
  167.    
  168.     #ifdef PlaneThread_h
  169.     static PlaneThread::SpinLock& GetLock() { static PlaneThread::SpinLock v; return v; };
  170.     static void lock() { GetLock().lock(); };
  171.     static void unlock() { GetLock().release(); };
  172.     #else
  173.     static void lock() { };
  174.     static void unlock() { };
  175.     #endif
  176.  
  177.     friend class Block;
  178. };
  179.  
  180. const StaticBuffer StaticBuffer_handle;
  181.  
  182. }; //end namespace
  183.  
  184. #endif //#ifndef PlaneGC_StaticBuffer_h
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top