switched to GPLv3 ONLY, because i don't trust FSF anymore
[amper.git] / egfx / util.d
blob8993930c3182614533666be88d6d284e11cd8f86
1 /* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 module egfx.util;
18 import iv.alice;
21 // ////////////////////////////////////////////////////////////////////////// //
22 alias KIdentity(T...) = T[0];
25 // ////////////////////////////////////////////////////////////////////////// //
26 public struct KRC(T) if (is(T == struct)) {
27 private:
28 usize intrp__;
30 private:
31 static void doIncRef (usize ox) nothrow @trusted @nogc {
32 pragma(inline, true);
33 if (ox) {
34 *cast(uint*)(ox-uint.sizeof) += 1;
35 version(krc_debug) { import core.stdc.stdio : printf; printf("doIncRef for 0x%08x (%u)\n", cast(uint)ox, *cast(uint*)(ox-uint.sizeof)); }
39 static void doDecRef() (ref usize ox) {
40 if (ox) {
41 version(krc_debug) { import core.stdc.stdio : printf; printf("doDecRef for 0x%08x (%u)\n", cast(uint)ox, *cast(uint*)(ox-uint.sizeof)); }
42 if ((*cast(uint*)(ox-uint.sizeof) -= 1) == 0) {
43 // kill and free
44 scope(exit) {
45 import core.stdc.stdlib : free;
46 import core.memory : GC;
48 version(krc_debug) { import core.stdc.stdio : printf; printf("CG CLEANUP FOR WRAPPER 0x%08x\n", cast(uint)ox); }
49 version(krc_debug) import core.stdc.stdio : printf;
50 void* mem = cast(void*)ox;
51 version(krc_debug) { import core.stdc.stdio : printf; printf("DESTROYING WRAPPER 0x%08x\n", cast(uint)mem); }
52 enum instSize = T.sizeof;
53 auto pbm = __traits(getPointerBitmap, T);
54 version(krc_debug) printf("[%.*s]: size=%u (%u) (%u)\n", cast(uint)T.stringof.length, T.stringof.ptr, cast(uint)pbm[0], cast(uint)instSize, cast(uint)(pbm[0]/size_t.sizeof));
55 immutable(ubyte)* p = cast(immutable(ubyte)*)(pbm.ptr+1);
56 size_t bitnum = 0;
57 immutable end = pbm[0]/size_t.sizeof;
58 while (bitnum < end) {
59 if (p[bitnum/8]&(1U<<(bitnum%8))) {
60 size_t len = 1;
61 while (bitnum+len < end && (p[(bitnum+len)/8]&(1U<<((bitnum+len)%8))) != 0) ++len;
62 version(krc_debug) printf(" #%u (%u)\n", cast(uint)(bitnum*size_t.sizeof), cast(uint)len);
63 GC.removeRange((cast(size_t*)mem)+bitnum);
64 bitnum += len;
65 } else {
66 ++bitnum;
70 free(cast(void*)(ox-uint.sizeof));
71 ox = 0;
73 (*cast(T*)ox).destroy;
78 public:
79 this(A...) (auto ref A args) {
80 intrp__ = newOx!T(args);
83 this() (auto ref typeof(this) src) nothrow @trusted @nogc {
84 intrp__ = src.intrp__;
85 doIncRef(intrp__);
88 ~this () { doDecRef(intrp__); }
90 this (this) nothrow @trusted @nogc { doIncRef(intrp__); }
92 void opAssign() (typeof(this) src) {
93 if (!intrp__ && !src.intrp__) return;
94 version(krc_debug) { import core.stdc.stdio : printf; printf("***OPASSIGN(0x%08x -> 0x%08x)\n", cast(void*)src.intrp__, cast(void*)intrp__); }
95 if (intrp__) {
96 // assigning to non-empty
97 if (src.intrp__) {
98 // both streams are active
99 if (intrp__ == src.intrp__) return; // nothing to do
100 auto oldo = intrp__;
101 auto newo = src.intrp__;
102 // first increase rc for new object
103 doIncRef(newo);
104 // replace object for this
105 intrp__ = newo;
106 // release old object
107 doDecRef(oldo);
108 } else {
109 // just close this one
110 scope(exit) intrp__ = 0;
111 doDecRef(intrp__);
113 } else if (src.intrp__) {
114 // this is empty, but other is not; easy deal
115 intrp__ = src.intrp__;
116 doIncRef(intrp__);
120 usize toHash () const pure nothrow @safe @nogc { pragma(inline, true); return intrp__; } // yeah, so simple
121 bool opEquals() (auto ref typeof(this) s) const { pragma(inline, true); return (intrp__ == s.intrp__); }
123 @property bool hasObject () const pure nothrow @trusted @nogc { pragma(inline, true); return (intrp__ != 0); }
125 @property inout(T)* intr_ () inout pure nothrow @trusted @nogc { pragma(inline, true); return cast(typeof(return))intrp__; }
127 // hack!
128 static if (__traits(compiles, ((){T s; bool v = s.valid;}))) {
129 @property bool valid () const nothrow @trusted @nogc { pragma(inline, true); return (intrp__ ? intr_.valid : false); }
132 alias intr_ this;
134 static private:
135 usize newOx (CT, A...) (auto ref A args) if (is(CT == struct)) {
136 import core.exception : onOutOfMemoryErrorNoGC;
137 import core.memory : GC;
138 import core.stdc.stdlib : malloc;
139 import core.stdc.string : memset;
140 import std.conv : emplace;
141 enum instSize = CT.sizeof;
142 // let's hope that malloc() aligns returned memory right
143 auto memx = malloc(instSize+uint.sizeof);
144 if (memx is null) onOutOfMemoryErrorNoGC(); // oops
145 memset(memx, 0, instSize+uint.sizeof);
146 *cast(uint*)memx = 1;
147 auto mem = memx+uint.sizeof;
148 emplace!CT(mem[0..instSize], args);
150 version(krc_debug) import core.stdc.stdio : printf;
151 auto pbm = __traits(getPointerBitmap, CT);
152 version(krc_debug) printf("[%.*s]: size=%u (%u) (%u)\n", cast(uint)CT.stringof.length, CT.stringof.ptr, cast(uint)pbm[0], cast(uint)instSize, cast(uint)(pbm[0]/size_t.sizeof));
153 immutable(ubyte)* p = cast(immutable(ubyte)*)(pbm.ptr+1);
154 size_t bitnum = 0;
155 immutable end = pbm[0]/size_t.sizeof;
156 while (bitnum < end) {
157 if (p[bitnum/8]&(1U<<(bitnum%8))) {
158 size_t len = 1;
159 while (bitnum+len < end && (p[(bitnum+len)/8]&(1U<<((bitnum+len)%8))) != 0) ++len;
160 version(krc_debug) printf(" #%u (%u)\n", cast(uint)(bitnum*size_t.sizeof), cast(uint)len);
161 GC.addRange((cast(size_t*)mem)+bitnum, size_t.sizeof*len);
162 bitnum += len;
163 } else {
164 ++bitnum;
167 version(krc_debug) { import core.stdc.stdio : printf; printf("CREATED WRAPPER 0x%08x\n", mem); }
168 return cast(usize)mem;