source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/ntl/uppalloc.cpp @ 1526

Revision 1526, 7.0 KB checked in by gumbau, 18 years ago (diff)

Updated modules to the new interface and the new simplification algorithm improvements.

Line 
1////////////////////////////////////////////////////////////////////////////////
2// NTL Nonstandard Template Library for C++
3// Copyright (c) 2003 by Miroslav Fidler, Tomas Rylek
4//
5// Created by Miroslav Fidler, Tomas Rylek, cxl@volny.cz
6//
7// Permission to use, copy, modify, distribute and sell this software for any
8//     purpose is hereby granted without fee, provided that the above copyright
9//     notice appear in all copies and that both that copyright notice and this
10//     permission notice appear in supporting documentation.
11// The author makes no representations about the suitability of this software
12//     for any purpose. It is provided "as is"
13//     without express or implied warranty.
14////////////////////////////////////////////////////////////////////////////////
15
16#include <stddef.h>
17#include <malloc.h>
18#include <stdlib.h>
19#include <string.h>
20#include <assert.h>
21
22#define LLOG(x)
23#define LTIMING(x)
24#define ASSERT(x) assert(x)
25
26namespace upp
27{
28
29typedef unsigned char  byte;
30typedef unsigned short word;
31typedef unsigned int   dword;
32
33struct BlockInfo {
34        BlockInfo *link;
35};
36
37struct PageLink {
38        PageLink  *bucket_next;
39        PageLink  *bucket_prev;
40        PageLink  *free_next;
41        PageLink  *free_prev;
42
43        void LinkSelf() {
44                bucket_next = bucket_prev = free_next = free_prev = this;
45        }
46        void UnlinkBucket() {
47                bucket_prev->bucket_next = bucket_next;
48                bucket_next->bucket_prev = bucket_prev;
49                bucket_next = bucket_prev = this;
50        }
51        void InsertBucket(PageLink *lnk) {
52                lnk->bucket_prev = this;
53                lnk->bucket_next = bucket_next;
54                bucket_next->bucket_prev = lnk;
55                bucket_next = lnk;
56        }
57        void UnlinkFree() {
58                free_prev->free_next = free_next;
59                free_next->free_prev = free_prev;
60                free_next = free_prev = this;
61        }
62        void InsertFree(PageLink *lnk) {
63                lnk->free_prev = this;
64                lnk->free_next = free_next;
65                free_next->free_prev = lnk;
66                free_next = lnk;
67        }
68};
69
70struct PageInfo : public PageLink {
71        BlockInfo *freelist;
72        byte      *memory;
73        word       freecount;
74        word       blockcount;
75        word       magnitude;
76        word       size;
77       
78        void Format(int m) {
79                LTIMING("Format");
80                ASSERT(m >= 0 && m <= 128);
81                magnitude = word(m);
82                size = word(4 * m);
83                byte *p = memory;
84                byte *e = memory + 2048 - size;
85                blockcount = 0;
86                freelist = NULL;
87                while(p <= e) {
88                        ((BlockInfo *)p)->link = freelist;
89                        freelist = (BlockInfo *)p;
90                        p += size;
91                        blockcount++;
92                }
93                freecount = blockcount;
94        }
95};
96
97
98typedef PageInfo *MemBook[512];
99
100MemBook  nullbook[1];
101MemBook *memmap[2048];
102
103PageInfo *NewPage()
104{
105        LTIMING("NewPage");
106        LLOG("Acquiring new page");
107        static int ci = 32;
108        static PageInfo *chunk;
109        if(ci >= 32) {
110                LLOG("**** Acquiring new 64KB block");
111                dword ptr = (dword)malloc(33 * 2048);
112                if(!ptr) return 0;
113                dword a = (ptr + 2047) & ~2047;
114                if(a - ptr >= 1024)
115                        chunk = (PageInfo *)ptr;
116                else
117                        chunk = (PageInfo *)(a + 32 * 2048);
118                byte *p = (byte *)a;
119                for(int i = 0; i < 32; i++) {
120                        chunk[i].LinkSelf();
121                        chunk[i].memory = p;
122                        p += 2048;
123                }
124                ci = 0;
125        }
126        PageInfo *p = chunk + ci++;
127        int pgi = ((dword)p->memory >> 11);
128        int bi = pgi >> 9;
129        pgi &= 511;
130        if(memmap[bi] == nullbook) {
131                memmap[bi] = (MemBook *)malloc(sizeof(MemBook));
132                memset(memmap[bi], 0, sizeof(MemBook));
133        }
134        (*memmap[bi])[pgi] = p;
135        return p;
136}
137
138
139#define InitLink2(a, n)         { a + n, a + n, a + n, a + n }, \
140                                { a + n + 1, a + n + 1, a + n + 1, a + n + 1 }
141#define InitLink4(a, n)         InitLink2(a, n),   InitLink2(a,   n + 2)
142#define InitLink8(a, n)         InitLink4(a, n),   InitLink4(a,   n + 4)
143#define InitLink16(a, n)        InitLink8(a, n),   InitLink8(a,   n + 8)
144#define InitLink32(a, n)        InitLink16(a, n),  InitLink16(a,  n + 16)
145#define InitLink64(a, n)        InitLink32(a, n),  InitLink32(a,  n + 32)
146
147PageLink bucket[129] = {
148        InitLink64(bucket, 0),
149        InitLink64(bucket, 64),
150        { bucket + 128, bucket + 128, bucket + 128, bucket + 128 }
151};
152
153PageLink free_bucket[129] = {
154        InitLink64(free_bucket, 0),
155        InitLink64(free_bucket, 64),
156        { free_bucket + 128, free_bucket + 128, free_bucket + 128, free_bucket + 128 }
157};
158
159PageLink emptylist[1] = {
160        { emptylist, emptylist, emptylist, emptylist }
161};
162
163byte size_magnitude[513];
164
165
166void GenerateMagnitudeTable(int *s)
167{
168        int size = 0;
169        int magnitude = *s / 4;
170        while(size <= 512) {
171                ASSERT(*s);
172                if(size > *s) {
173                        s++;
174                        magnitude = *s / 4;
175                }
176                size_magnitude[size] = byte(magnitude);
177                size++;
178        }
179        ASSERT(*s == 512);
180}
181
182
183void *Alloc(size_t size)
184{
185        LTIMING("Alloc");
186        LLOG("Alloc(" << size << ")");
187        if(size <= 512) {
188                int m = size_magnitude[size];
189                PageLink& bm = bucket[m];
190                PageInfo *page = (PageInfo *)bm.bucket_next;
191                BlockInfo *q;
192                if(page != &bm) {
193                        ASSERT(page->freecount > 0 && page->freecount < page->blockcount);
194                        LLOG("Allocating from page " << Dump(page));
195                        q = page->freelist;
196                        page->freelist = q->link;
197                        if(--page->freecount == 0) {
198                                LLOG("Page exhausted " << Dump(page));
199                                page->UnlinkBucket();
200                        }
201                        return q;
202                }
203                page = (PageInfo *)free_bucket[m].bucket_next; 
204                if(page != &free_bucket[m]) {
205                        LLOG("Next empty bucket page " << Dump(page));
206                        ASSERT(page->freecount == page->blockcount);
207                        page->UnlinkFree();
208                        page->UnlinkBucket();
209                        bm.InsertBucket(page);
210                        q = page->freelist;
211                        page->freelist = q->link;
212                        if(--page->freecount == 0)
213                                page->UnlinkBucket();
214                        return q;
215                }
216                page = (PageInfo *)emptylist->free_next;
217                if(page != emptylist) {
218                        ASSERT(page->freecount == page->blockcount);
219                        LLOG("Recycling page " << Dump(page));
220                        page->UnlinkFree();
221                        page->UnlinkBucket();
222                }
223                else {
224                        static bool init;
225                        if(!init) {
226                                init = true;
227                                static int mtable1[] = { 4, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112,
228                                                     128, 144, 168, 200, 256, 336, 408, 512 };
229                                GenerateMagnitudeTable(mtable1);
230                                for(int i = 0; i < 2048; i++)
231                                        memmap[i] = nullbook;
232                                m = size_magnitude[size];
233                        }
234                        page = NewPage();
235                        if (page == 0) return 0;
236
237                }
238                page->Format(m);
239                LLOG("Formated page " << Dump(page));
240                bucket[m].InsertBucket(page);
241                q = page->freelist;
242                page->freelist = q->link;
243                page->freecount--;
244                return q;
245        }
246        void *q = malloc(size);
247        return q;
248}
249
250
251void Free(void *ptr)
252{
253        int pgi = ((dword)ptr >> 11);
254        PageInfo *page = (*memmap[pgi >> 9])[pgi & 511];
255        if(page) {
256                ASSERT(((dword)ptr & 2047) % page->size == 0);
257                BlockInfo *b = (BlockInfo *)ptr;
258                b->link = page->freelist;
259                page->freelist = b;
260                if(page->bucket_next == page) {
261                        LLOG("Putting to bucket " << Dump(page));
262                        bucket[page->magnitude].InsertBucket(page);
263                }
264                LLOG("Freeing in page " << Dump(page));
265                if(++page->freecount == page->blockcount) {
266                        page->UnlinkBucket();
267                        free_bucket[page->magnitude].InsertBucket(page);
268                        emptylist->InsertFree(page);
269                        LLOG("Moving to empty " << Dump(page));
270                }
271                ASSERT(page->freecount <= page->blockcount);
272        }
273        else
274                free(ptr);
275}
276
277}//namespace upp
278
279#undef LLOG
280#undef LTIMING
Note: See TracBrowser for help on using the repository browser.