source: trunk/lib/allocator.hpp @ 4050

Last change on this file since 4050 was 2286, checked in by ksherdy, 7 years ago

Removed problematic 'using namespace std;'

File size: 4.4 KB
RevLine 
[1748]1#ifndef ALLOCATOR_HPP_
2#define ALLOCATOR_HPP_
[1946]3/*=============================================================================
4  allocator.hpp - Coterminal memory pool allocators.
5  Created on: 18-December-2011
6  Author: Ken Herdy
7=============================================================================*/
[1748]8
9#include "debug.hpp"
[1935]10#include "bitblock.hpp"
[1748]11#include <assert.h>
12#include <stdint.h>
13#include <stdlib.h>
14
15#include <iostream>
16
[1946]17///////////////////////////////////////////////////////////////////////////////
18// Base Class
19///////////////////////////////////////////////////////////////////////////////
[1748]20class pool_allocator {
21public:
[1811]22        /* n - bytes requested, allocd_segment_size - bytes allocated */
23        void * allocate (uint64_t n, uint64_t & allocd_segment_size);
24        void * allocate_aligned (uint64_t n, uint64_t & allocd_segment_size);
[1748]25        void destroy ();
26protected:
27        pool_allocator(){}
28        ~pool_allocator(){}
29};
30
[1946]31///////////////////////////////////////////////////////////////////////////////
32// Fast Memory Pool Allocator - Trade memory for speed.
33//
34// Allocates BASE_SIZE initial bytes on the stack.
35// Additional memory allocated on the heap. Coterminal deallocation.
36// Allocation returns void * pointer to memory block,
37// Returns number of bytes allocated.
38//
39///////////////////////////////////////////////////////////////////////////////
[1748]40template<uint32_t BASE_SIZE>
[1758]41class fast_pool_allocator : public pool_allocator {
[1748]42
43public:
[1758]44        fast_pool_allocator(const uint8_t align=64, const uint8_t exp=2): ALIGNMENT(align), EXPANSION_FACTOR(exp) {
[1748]45                tail = &head;
46                tail->segment = stack_segment;
47                tail->next = NULL;
48                available = BASE_SIZE;
49                segment_size = BASE_SIZE;
50        }
51
[1758]52        ~fast_pool_allocator() {}
[1748]53
[1811]54        void * allocate(uint64_t n, uint64_t & allocd_segment_size) {
[1935]55
[1758]56                if(n > available) {
57                        segment_size = next_segment_size(n);
58
59                        node * next = (node *) malloc(sizeof(node));
60                        if (next == NULL) {
[2286]61                std::cerr << "Out of Memory" << std::endl;
[1758]62                                abort();
63                        }
64
65                        next->segment = (uint8_t *) malloc(segment_size);
66                        if ((next->segment) == NULL) {
[2286]67                std::cerr << "Out of Memory" << std::endl;
[1758]68                                abort();
69                        }
70
71                        next->next = NULL;
72                        tail->next = next;
73                        tail = next;
[1938]74
75                        uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[0]));
76                        allocd_segment_size = segment_size;
77                        available = 0;
78
79                        return (void *) (address);
[1758]80                }
81
82                uint32_t i = segment_size - available;
83                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
84
[1937]85                allocd_segment_size = n;
[1763]86                available -= n;
87
[1758]88                return (void *) (address);
89        }
[1938]90
[1935]91        void * allocate_aligned(uint64_t n, uint64_t & allocd_segment_size) {
[1758]92
[1748]93                uint64_t n_padded = (n+ALIGNMENT-1);
94
95                if(n_padded > available) {
[1763]96
[1748]97                        segment_size = next_segment_size(n_padded);
98
99                        node * next = (node *) malloc(sizeof(node));
100                        if (next == NULL) {
[2286]101                std::cerr << "Out of Memory" << std::endl;
[1748]102                                abort();
103                        }
104
105                        next->segment = (uint8_t *) malloc(segment_size);
106                        if ((next->segment) == NULL) {
[2286]107                std::cerr << "Out of Memory" << std::endl;
[1748]108                                abort();
109                        }
110
111                        next->next = NULL;
112                        tail->next = next;
113                        tail = next;
[1938]114
115                        uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[0]));
116                        uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
117                        allocd_segment_size = segment_size - padding;
118                        available = 0;
119
120                        assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
121                        return (void *) (address + padding);
[1748]122                }
123
124                uint32_t i = segment_size - available;
[1758]125                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
[1748]126                uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
[1938]127                allocd_segment_size = n - padding;
[1748]128                available -= (padding + n);
129
130                assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
131
132                return (void *) (address + padding);
133        }
[1938]134
[1748]135        void destroy() {
136                node * crt = head.next;
137                node * next;
138                while(crt != NULL) {
139                        next = crt->next;
140                        free((uint8_t *) crt->segment);
141                        free((node *)crt);
142                        crt = next;
143                        next = NULL;
144                }
145        }
146
[1763]147        uint64_t get_alloc_size() const { return alloc_size; }
148
[1748]149private:
[1763]150        uint64_t alloc_size;
151
[1748]152        const uint8_t ALIGNMENT;
153        const uint8_t EXPANSION_FACTOR;
154        uint64_t available;
155        uint64_t segment_size;
156
157        typedef struct node {
158                node * next;
159                uint8_t * segment;
160        } node;
161
162        uint8_t stack_segment[BASE_SIZE];
163        node head;
164        node * tail;
165
166        uint64_t next_segment_size(uint64_t n) const {
167                return (((n/segment_size) * segment_size) + segment_size) * EXPANSION_FACTOR ; // a multiple of segment_size
168        }
169
170};
171
[1946]172#endif // ALLOCATOR_HPP_
Note: See TracBrowser for help on using the repository browser.