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/>.
21 // ////////////////////////////////////////////////////////////////////////// //
22 alias KIdentity(T
...) = T
[0];
25 // ////////////////////////////////////////////////////////////////////////// //
26 public struct KRC(T
) if (is(T
== struct)) {
31 static void doIncRef (usize ox
) nothrow @trusted @nogc {
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
) {
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) {
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);
57 immutable end
= pbm
[0]/size_t
.sizeof
;
58 while (bitnum
< end
) {
59 if (p
[bitnum
/8]&(1U<<(bitnum
%8))) {
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
);
70 free(cast(void*)(ox
-uint.sizeof
));
73 (*cast(T
*)ox
).destroy
;
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__
;
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__
); }
96 // assigning to non-empty
98 // both streams are active
99 if (intrp__
== src
.intrp__
) return; // nothing to do
101 auto newo
= src
.intrp__
;
102 // first increase rc for new object
104 // replace object for this
106 // release old object
109 // just close this one
110 scope(exit
) intrp__
= 0;
113 } else if (src
.intrp__
) {
114 // this is empty, but other is not; easy deal
115 intrp__
= src
.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__
; }
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); }
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);
155 immutable end
= pbm
[0]/size_t
.sizeof
;
156 while (bitnum
< end
) {
157 if (p
[bitnum
/8]&(1U<<(bitnum
%8))) {
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
);
167 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("CREATED WRAPPER 0x%08x\n", mem
); }
168 return cast(usize
)mem
;