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