comparison src/impl/hoofbaby/util/memory.d @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /**
2 * Hoofbaby -- http://www.dsource.org/projects/hoofbaby
3 * Copyright (C) 2009 Robert Fraser
4 *
5 * This program is free software; you can redistribute it andor
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16 module hoofbaby.util.memory;
17
18 import tango.core.Memory : GC;
19 import candy.util.array;
20
21 /**
22 * Provides a pool of GCed memory to allocate things from a block.
23 * This maintains cache coherency for related types (i.e. tree nodes).
24 * It doesn't garuntee any ordering, though, the array struct should be
25 * used for that. Also, everything has to be freed at once, freeing one
26 * portion of this has no effect.
27 *
28 * Based on a similar concept posted by bearophile at:
29 * http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=88227
30 */
31 public struct MemPool(size_t BLOCK_SIZE = 1 << 14)
32 {
33 private void* next; // Next available block
34 private void* end; // End of the current block
35 private void*[] blocks;
36
37 public void* alloc(size_t sz)
38 {
39 sz = ((sz + 7) & ~7); // Next multiple of 8 if this isn't a multiple of 8
40 if (this.next + sz >= this.end)
41 {
42 void* blk = GC.calloc(BLOCK_SIZE);
43 this.blocks.length = this.blocks.length + 1;
44 this.blocks[$ - 1] = blk;
45 this.next = blk;
46 this.end = blk + BLOCK_SIZE;
47 }
48
49 void* ret = this.next;
50 this.next += sz;
51 return ret;
52 }
53
54 public void free()
55 {
56 foreach(blk; this.blocks)
57 GC.free(blk);
58 this.blocks = null;
59 this.blocks.length = 0;
60 this.next = null;
61 this.end = null;
62 }
63 }
64
65 /**
66 * Wrapper for MemPool that allocates the given struct
67 */
68 public struct StructPool(T)
69 {
70 private MemPool!() pool;
71 public T* alloc() { return cast(T*) pool.alloc(T.sizeof); }
72 }
73
74 public struct MemStack(size_t BLOCK_SIZE = 1 << 14)
75 {
76 private Stack!(MemPool!(BLOCK_SIZE)*, 16, true, true) stack;
77 public static const size_t MAX_ALLOC = BLOCK_SIZE;
78
79 public void* alloc(size_t sz) { return stack.peek().alloc(sz); }
80 public void push() { stack.push(new MemPool!(BLOCK_SIZE)); }
81 public void pop() { stack.pop().free(); }
82 }
83
84 /**
85 * Placement new mixin for allocating from a memory pool. Benchmarks show this
86 * as faster than the D new in real usage (i.e. the parser runs about 1.2x
87 * faster using this).
88 */
89 public template MemPoolNew(alias Pool)
90 {
91 version(NoMemPool) { } else
92 {
93 public final new(uint sz) { return Pool.alloc(sz); }
94 public final delete(void *p) { }
95 }
96 }