source: trunk/lib/allocator.hpp @ 1935

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

Fixed allocation bug in standard allocation method.

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