1 /**
2  * Contains a bitfield used by the GC.
3  *
4  * Copyright: Copyright Digital Mars 2005 - 2013.
5  * License:   $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
6  * Authors:   Walter Bright, David Friedman, Sean Kelly
7  */
8 
9 /*          Copyright Digital Mars 2005 - 2013.
10  * Distributed under the Boost Software License, Version 1.0.
11  *    (See accompanying file LICENSE or copy at
12  *          http://www.boost.org/LICENSE_1_0.txt)
13  */
14 module gc.bits;
15 
16 
17 import core.bitop;
18 import core.stdc.string;
19 import core.stdc.stdlib;
20 import core.exception : onOutOfMemoryError;
21 
22 struct GCBits
23 {
24     alias size_t wordtype;
25 
26     enum BITS_PER_WORD = (wordtype.sizeof * 8);
27     enum BITS_SHIFT = (wordtype.sizeof == 8 ? 6 : 5);
28     enum BITS_MASK = (BITS_PER_WORD - 1);
29     enum BITS_1 = cast(wordtype)1;
30 
31     wordtype* data;
32     size_t nbits;
33 
DtorGCBits34     void Dtor() nothrow
35     {
36         if (data)
37         {
38             free(data);
39             data = null;
40         }
41     }
42 
allocGCBits43     void alloc(size_t nbits) nothrow
44     {
45         this.nbits = nbits;
46         data = cast(typeof(data[0])*)calloc(nwords, data[0].sizeof);
47         if (!data)
48             onOutOfMemoryError();
49     }
50 
testGCBits51     wordtype test(size_t i) const nothrow
52     in
53     {
54         assert(i < nbits);
55     }
56     body
57     {
58         return core.bitop.bt(data, i);
59     }
60 
setGCBits61     int set(size_t i) nothrow
62     in
63     {
64         assert(i < nbits);
65     }
66     body
67     {
68         return core.bitop.bts(data, i);
69     }
70 
clearGCBits71     int clear(size_t i) nothrow
72     in
73     {
74         assert(i <= nbits);
75     }
76     body
77     {
78         return core.bitop.btr(data, i);
79     }
80 
zeroGCBits81     void zero() nothrow
82     {
83         memset(data, 0, nwords * wordtype.sizeof);
84     }
85 
copyGCBits86     void copy(GCBits *f) nothrow
87     in
88     {
89         assert(nwords == f.nwords);
90     }
91     body
92     {
93         memcpy(data, f.data, nwords * wordtype.sizeof);
94     }
95 
nwordsGCBits96     @property size_t nwords() const pure nothrow
97     {
98         return (nbits + (BITS_PER_WORD - 1)) >> BITS_SHIFT;
99     }
100 }
101 
102 unittest
103 {
104     GCBits b;
105 
106     b.alloc(786);
107     assert(!b.test(123));
108     assert(!b.clear(123));
109     assert(!b.set(123));
110     assert(b.test(123));
111     assert(b.clear(123));
112     assert(!b.test(123));
113 
114     b.set(785);
115     b.set(0);
116     assert(b.test(785));
117     assert(b.test(0));
118     b.zero();
119     assert(!b.test(785));
120     assert(!b.test(0));
121 
122     GCBits b2;
123     b2.alloc(786);
124     b2.set(38);
125     b.copy(&b2);
126     assert(b.test(38));
127     b2.Dtor();
128     b.Dtor();
129 }
130