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