source: trunk/lib/allocator.hpp @ 1842

Last change on this file since 1842 was 1842, checked in by ksherdy, 8 years ago

Added comment.

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