source: trunk/lib/allocator.hpp @ 2093

Last change on this file since 2093 was 2051, checked in by ksherdy, 7 years ago

Removed BOO.

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                if(n_padded > available) {
97
98                        segment_size = next_segment_size(n_padded);
99
100                        node * next = (node *) malloc(sizeof(node));
101                        if (next == NULL) {
102                                cerr << "Out of Memory" << endl;
103                                abort();
104                        }
105
106                        next->segment = (uint8_t *) malloc(segment_size);
107                        if ((next->segment) == NULL) {
108                                cerr << "Out of Memory" << endl;
109                                abort();
110                        }
111
112                        next->next = NULL;
113                        tail->next = next;
114                        tail = next;
115
116                        uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[0]));
117                        uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
118                        allocd_segment_size = segment_size - padding;
119                        available = 0;
120
121                        assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
122                        return (void *) (address + padding);
123                }
124
125                uint32_t i = segment_size - available;
126                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
127                uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
128                allocd_segment_size = n - padding;
129                available -= (padding + n);
130
131                assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
132
133                return (void *) (address + padding);
134        }
135
136        void destroy() {
137                node * crt = head.next;
138                node * next;
139                while(crt != NULL) {
140                        next = crt->next;
141                        free((uint8_t *) crt->segment);
142                        free((node *)crt);
143                        crt = next;
144                        next = NULL;
145                }
146        }
147
148        uint64_t get_alloc_size() const { return alloc_size; }
149
150private:
151        uint64_t alloc_size;
152
153        const uint8_t ALIGNMENT;
154        const uint8_t EXPANSION_FACTOR;
155        uint64_t available;
156        uint64_t segment_size;
157
158        typedef struct node {
159                node * next;
160                uint8_t * segment;
161        } node;
162
163        uint8_t stack_segment[BASE_SIZE];
164        node head;
165        node * tail;
166
167        uint64_t next_segment_size(uint64_t n) const {
168                return (((n/segment_size) * segment_size) + segment_size) * EXPANSION_FACTOR ; // a multiple of segment_size
169        }
170
171};
172
173#endif // ALLOCATOR_HPP_
Note: See TracBrowser for help on using the repository browser.