cosmetix
[amper.git] / egfx / util.d
blob06aeeafcde9a3be4d83776640cd642c75110e3f6
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, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module egfx.util;
19 import iv.alice;
22 // ////////////////////////////////////////////////////////////////////////// //
23 alias KIdentity(T...) = T[0];
26 // ////////////////////////////////////////////////////////////////////////// //
27 public struct KRC(T) if (is(T == struct)) {
28 private:
29 usize intrp__;
31 private:
32 static void doIncRef (usize ox) nothrow @trusted @nogc {
33 pragma(inline, true);
34 if (ox) {
35 *cast(uint*)(ox-uint.sizeof) += 1;
36 version(krc_debug) { import core.stdc.stdio : printf; printf("doIncRef for 0x%08x (%u)\n", cast(uint)ox, *cast(uint*)(ox-uint.sizeof)); }
40 static void doDecRef() (ref usize ox) {
41 if (ox) {
42 version(krc_debug) { import core.stdc.stdio : printf; printf("doDecRef for 0x%08x (%u)\n", cast(uint)ox, *cast(uint*)(ox-uint.sizeof)); }
43 if ((*cast(uint*)(ox-uint.sizeof) -= 1) == 0) {
44 // kill and free
45 scope(exit) {
46 import core.stdc.stdlib : free;
47 import core.memory : GC;
49 version(krc_debug) { import core.stdc.stdio : printf; printf("CG CLEANUP FOR WRAPPER 0x%08x\n", cast(uint)ox); }
50 version(krc_debug) import core.stdc.stdio : printf;
51 void* mem = cast(void*)ox;
52 version(krc_debug) { import core.stdc.stdio : printf; printf("DESTROYING WRAPPER 0x%08x\n", cast(uint)mem); }
53 enum instSize = T.sizeof;
54 auto pbm = __traits(getPointerBitmap, T);
55 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));
56 immutable(ubyte)* p = cast(immutable(ubyte)*)(pbm.ptr+1);
57 size_t bitnum = 0;
58 immutable end = pbm[0]/size_t.sizeof;
59 while (bitnum < end) {
60 if (p[bitnum/8]&(1U<<(bitnum%8))) {
61 size_t len = 1;
62 while (bitnum+len < end && (p[(bitnum+len)/8]&(1U<<((bitnum+len)%8))) != 0) ++len;
63 version(krc_debug) printf(" #%u (%u)\n", cast(uint)(bitnum*size_t.sizeof), cast(uint)len);
64 GC.removeRange((cast(size_t*)mem)+bitnum);
65 bitnum += len;
66 } else {
67 ++bitnum;
71 free(cast(void*)(ox-uint.sizeof));
72 ox = 0;
74 (*cast(T*)ox).destroy;
79 public:
80 this(A...) (auto ref A args) {
81 intrp__ = newOx!T(args);
84 this() (auto ref typeof(this) src) nothrow @trusted @nogc {
85 intrp__ = src.intrp__;
86 doIncRef(intrp__);
89 ~this () { doDecRef(intrp__); }
91 this (this) nothrow @trusted @nogc { doIncRef(intrp__); }
93 void opAssign() (typeof(this) src) {
94 if (!intrp__ && !src.intrp__) return;
95 version(krc_debug) { import core.stdc.stdio : printf; printf("***OPASSIGN(0x%08x -> 0x%08x)\n", cast(void*)src.intrp__, cast(void*)intrp__); }
96 if (intrp__) {
97 // assigning to non-empty
98 if (src.intrp__) {
99 // both streams are active
100 if (intrp__ == src.intrp__) return; // nothing to do
101 auto oldo = intrp__;
102 auto newo = src.intrp__;
103 // first increase rc for new object
104 doIncRef(newo);
105 // replace object for this
106 intrp__ = newo;
107 // release old object
108 doDecRef(oldo);
109 } else {
110 // just close this one
111 scope(exit) intrp__ = 0;
112 doDecRef(intrp__);
114 } else if (src.intrp__) {
115 // this is empty, but other is not; easy deal
116 intrp__ = src.intrp__;
117 doIncRef(intrp__);
121 usize toHash () const pure nothrow @safe @nogc { pragma(inline, true); return intrp__; } // yeah, so simple
122 bool opEquals() (auto ref typeof(this) s) const { pragma(inline, true); return (intrp__ == s.intrp__); }
124 @property bool hasObject () const pure nothrow @trusted @nogc { pragma(inline, true); return (intrp__ != 0); }
126 @property inout(T)* intr_ () inout pure nothrow @trusted @nogc { pragma(inline, true); return cast(typeof(return))intrp__; }
128 // hack!
129 static if (__traits(compiles, ((){T s; bool v = s.valid;}))) {
130 @property bool valid () const nothrow @trusted @nogc { pragma(inline, true); return (intrp__ ? intr_.valid : false); }
133 alias intr_ this;
135 static private:
136 usize newOx (CT, A...) (auto ref A args) if (is(CT == struct)) {
137 import core.exception : onOutOfMemoryErrorNoGC;
138 import core.memory : GC;
139 import core.stdc.stdlib : malloc;
140 import core.stdc.string : memset;
141 import std.conv : emplace;
142 enum instSize = CT.sizeof;
143 // let's hope that malloc() aligns returned memory right
144 auto memx = malloc(instSize+uint.sizeof);
145 if (memx is null) onOutOfMemoryErrorNoGC(); // oops
146 memset(memx, 0, instSize+uint.sizeof);
147 *cast(uint*)memx = 1;
148 auto mem = memx+uint.sizeof;
149 emplace!CT(mem[0..instSize], args);
151 version(krc_debug) import core.stdc.stdio : printf;
152 auto pbm = __traits(getPointerBitmap, CT);
153 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));
154 immutable(ubyte)* p = cast(immutable(ubyte)*)(pbm.ptr+1);
155 size_t bitnum = 0;
156 immutable end = pbm[0]/size_t.sizeof;
157 while (bitnum < end) {
158 if (p[bitnum/8]&(1U<<(bitnum%8))) {
159 size_t len = 1;
160 while (bitnum+len < end && (p[(bitnum+len)/8]&(1U<<((bitnum+len)%8))) != 0) ++len;
161 version(krc_debug) printf(" #%u (%u)\n", cast(uint)(bitnum*size_t.sizeof), cast(uint)len);
162 GC.addRange((cast(size_t*)mem)+bitnum, size_t.sizeof*len);
163 bitnum += len;
164 } else {
165 ++bitnum;
168 version(krc_debug) { import core.stdc.stdio : printf; printf("CREATED WRAPPER 0x%08x\n", mem); }
169 return cast(usize)mem;