source: trunk/lib/allocator.hpp @ 1750

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

Updated C style cast to C++ reinterpret_cast.

File size: 2.4 KB
Line 
1/*
2 * allocator.hpp - Memory allocation.
3 */
4
5
6#ifndef ALLOCATOR_HPP_
7#define ALLOCATOR_HPP_
8
9#include "debug.hpp"
10#include <assert.h>
11#include <stdint.h>
12#include <stdlib.h>
13
14#include <iostream>
15using namespace std;
16
17/* Base Class */
18class pool_allocator {
19public:
20        void * allocate ();
21        void destroy ();
22protected:
23        pool_allocator(){}
24        ~pool_allocator(){}
25};
26
27/* Aligned Memory Allocator - A fast memory allocator. Trade memory for speed.
28 *
29 * Allocates BASE_SIZE stack bytes.
30 * Allocates additional bytes on the heap.
31 * Returns aligned raw data pointers (void *).
32 * Simultaneous deallocation.
33 *
34 */
35template<uint32_t BASE_SIZE>
36class aligned_pool_allocator : public pool_allocator {
37
38public:
39        aligned_pool_allocator(const uint8_t align=64, const uint8_t exp=2): ALIGNMENT(align), EXPANSION_FACTOR(exp) {
40                tail = &head;
41                tail->segment = stack_segment;
42                tail->next = NULL;
43                available = BASE_SIZE;
44                segment_size = BASE_SIZE;
45        }
46
47        ~aligned_pool_allocator() {}
48
49        void * allocate(uint64_t n) {
50                uint64_t n_padded = (n+ALIGNMENT-1);
51
52                if(n_padded > available) {
53                        segment_size = next_segment_size(n_padded);
54
55                        node * next = (node *) malloc(sizeof(node));
56                        if (next == NULL) {
57                                cerr << "Out of Memory" << endl;
58                                abort();
59                        }
60
61                        next->segment = (uint8_t *) malloc(segment_size);
62                        if ((next->segment) == NULL) {
63                                cerr << "Out of Memory" << endl;
64                                abort();
65                        }
66
67                        available = segment_size;
68
69                        next->next = NULL;
70                        tail->next = next;
71                        tail = next;
72                        next = NULL;
73                }
74
75                uint32_t i = segment_size - available;
76                uint64_t address = reinterpret_cast<uint64_t>(&(tail->segment[i]));
77                uint64_t padding = ((address % ALIGNMENT) == 0) ? 0 :  ALIGNMENT - (address % ALIGNMENT);
78                available -= (padding + n);
79
80                assert(((uint64_t)(address + padding))%ALIGNMENT == 0);
81
82                return (void *) (address + padding);
83        }
84
85        void destroy() {
86                node * crt = head.next;
87                node * next;
88                while(crt != NULL) {
89                        next = crt->next;
90                        free((uint8_t *) crt->segment);
91                        free((node *)crt);
92                        crt = next;
93                        next = NULL;
94                }
95        }
96
97private:
98        const uint8_t ALIGNMENT;
99        const uint8_t EXPANSION_FACTOR;
100        uint64_t available;
101        uint64_t segment_size;
102
103        typedef struct node {
104                node * next;
105                uint8_t * segment;
106        } node;
107
108        uint8_t stack_segment[BASE_SIZE];
109        node head;
110        node * tail;
111
112        uint64_t next_segment_size(uint64_t n) const {
113                return (((n/segment_size) * segment_size) + segment_size) * EXPANSION_FACTOR ; // a multiple of segment_size
114        }
115
116};
117
118#endif
Note: See TracBrowser for help on using the repository browser.