source: trunk/lib_c/allocator.h @ 3478

Last change on this file since 3478 was 3391, checked in by linmengl, 6 years ago

check in IDISA C library and other support libraries. Some template features still remain.

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