source: trunk/lib/allocator.hpp @ 2039

Last change on this file since 2039 was 1946, checked in by ksherdy, 7 years ago

Updated comments.

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