source: trunk/lib/allocator.hpp @ 5715

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

Removed problematic 'using namespace std;'

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>
16
17///////////////////////////////////////////////////////////////////////////////
18// Base Class
19///////////////////////////////////////////////////////////////////////////////
20class pool_allocator {
21public:
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);
25        void destroy ();
26protected:
27        pool_allocator(){}
28        ~pool_allocator(){}
29};
30
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///////////////////////////////////////////////////////////////////////////////
40template<uint32_t BASE_SIZE>
41class fast_pool_allocator : public pool_allocator {
42
43public:
44        fast_pool_allocator(const uint8_t align=64, const uint8_t exp=2): ALIGNMENT(align), EXPANSION_FACTOR(exp) {
45                tail = &head;
46                tail->segment = stack_segment;
47                tail->next = NULL;
48                available = BASE_SIZE;
49                segment_size = BASE_SIZE;
50        }
51
52        ~fast_pool_allocator() {}
53
54        void * allocate(uint64_t n, uint64_t & allocd_segment_size) {
55
56                if(n > available) {
57                        segment_size = next_segment_size(n);
58
59                        node * next = (node *) malloc(sizeof(node));
60                        if (next == NULL) {
61                std::cerr << "Out of Memory" << std::endl;
62                                abort();
63                        }
64
65                        next->segment = (uint8_t *) malloc(segment_size);
66                        if ((next->segment) == NULL) {
67                std::cerr << "Out of Memory" << std::endl;
68                                abort();
69                        }
70
71                        next->next = NULL;
72                        tail->next = next;
73                        tail = next;
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);
80                }
81
82                uint32_t i = segment_size - available;
83                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
84
85                allocd_segment_size = n;
86                available -= n;
87
88                return (void *) (address);
89        }
90
91        void * allocate_aligned(uint64_t n, uint64_t & allocd_segment_size) {
92
93                uint64_t n_padded = (n+ALIGNMENT-1);
94
95                if(n_padded > available) {
96
97                        segment_size = next_segment_size(n_padded);
98
99                        node * next = (node *) malloc(sizeof(node));
100                        if (next == NULL) {
101                std::cerr << "Out of Memory" << std::endl;
102                                abort();
103                        }
104
105                        next->segment = (uint8_t *) malloc(segment_size);
106                        if ((next->segment) == NULL) {
107                std::cerr << "Out of Memory" << std::endl;
108                                abort();
109                        }
110
111                        next->next = NULL;
112                        tail->next = next;
113                        tail = next;
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);
122                }
123
124                uint32_t i = segment_size - available;
125                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
126                uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
127                allocd_segment_size = n - padding;
128                available -= (padding + n);
129
130                assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
131
132                return (void *) (address + padding);
133        }
134
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
147        uint64_t get_alloc_size() const { return alloc_size; }
148
149private:
150        uint64_t alloc_size;
151
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
172#endif // ALLOCATOR_HPP_
Note: See TracBrowser for help on using the repository browser.