Skip to content

Commit f4e42bf

Browse files
Clean up numem.rc
1 parent 29b2205 commit f4e42bf

File tree

2 files changed

+90
-80
lines changed

2 files changed

+90
-80
lines changed

source/numem/rc.d

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,78 @@
99
Authors: Luna Nielsen
1010
*/
1111
module numem.rc;
12+
import numem.core.lifetime;
1213
import numem.core.hooks;
14+
import numem.core.traits;
1315
import numem.lifetime;
1416

1517
/**
16-
A reference counted container.
18+
A semi-automatically reference counted value container.
1719
*/
1820
struct Rc(T) {
19-
public:
21+
private:
2022
@nogc:
21-
mixin RcBase!T;
23+
alias RCT = __rc!T;
24+
RCT* rc;
25+
26+
pragma(inline, true)
27+
void __retain() @trusted {
28+
if (rc) {
29+
nu_atomic_add_32(rc.refs, 1);
30+
}
31+
}
32+
33+
pragma(inline, true)
34+
void __release() @trusted {
35+
if (rc) {
36+
if (nu_atomic_sub_32(rc.refs, 1) == 1) {
37+
nogc_trydelete(rc.value);
38+
nu_free(rc);
39+
40+
}
41+
}
42+
this.rc = null;
43+
}
44+
45+
public:
46+
alias value this;
2247

2348
/**
24-
Creates an reference counted object using given $(D value).
49+
Whether the RC value is valid.
50+
*/
51+
@property bool isValid() inout nothrow @safe => rc !is null;
52+
53+
/**
54+
The value stored in the rc type.
55+
*/
56+
@property ref inout(T) value() inout nothrow @safe => cast(inout(T))rc.value;
57+
58+
/// Destructor
59+
~this() {
60+
this.__release();
61+
}
62+
63+
/**
64+
Creates an reference counted object using given $(D value),
65+
if value is given by reference, it is moved to the Rc.
2566
2667
Params:
2768
value = The value.
2869
*/
29-
this(T value) @trusted {
30-
this.rc = nogc_new!__rc(1, value);
70+
this(in inout(T) value) @trusted {
71+
RCT* rc = cast(RCT*)nu_malloc(RCT.sizeof);
72+
rc.value = cast(T)value;
73+
rc.refs = 1;
74+
75+
nu_atomic_store_ptr(cast(void**)&this.rc, rc);
76+
}
77+
78+
/**
79+
Copy constructor
80+
*/
81+
this(ref return scope inout(typeof(this)) rhs) @trusted {
82+
this.rc = cast(RCT*)rhs.rc;
83+
this.__retain();
3184
}
3285

3386
/**
@@ -46,76 +99,28 @@ public:
4699
this.__release();
47100
return this;
48101
}
49-
}
50-
51-
/**
52-
Automatically reference counted value.
53-
*/
54-
struct Arc(T) {
55-
public:
56-
@nogc:
57-
mixin RcBase!T;
58-
59-
/// Destructor
60-
~this() {
61-
this.__release();
62-
}
63102

64103
/**
65-
Creates an reference counted object using given $(D value).
66-
67-
Params:
68-
value = The value.
104+
Implements implicit cast for RC value validity.
69105
*/
70-
this(T value) @trusted {
71-
this.rc = nogc_new!__rc(1, value);
72-
}
106+
T opCast(T : bool)() inout nothrow @safe => isValid();
73107

74108
/**
75-
Copy constructor
109+
Implements base cast
76110
*/
77-
this(ref return scope inout(typeof(this)) rhs) inout @trusted {
78-
this.rc = rhs.rc;
79-
(cast(Arc!T)this).__retain();
111+
ref T opCast(T : typeof(this))() inout nothrow {
112+
return *(cast(T*)(cast(void**)&rc.value));
80113
}
81114
}
82115

83-
// Base RefCounted.
84-
private mixin template RcBase(T) {
116+
//
117+
// IMPLEMENTATION DETAILS
118+
//
85119
private:
86-
@nogc:
87-
static struct __rc {
88-
private:
89-
@nogc:
90-
uint refs;
91-
T value;
92-
}
93-
94-
__rc* rc;
95120

96-
pragma(inline, true)
97-
void __retain() @trusted nothrow {
98-
if (rc) {
99-
nu_atomic_add_32(rc.refs, 1);
100-
}
101-
}
102-
103-
pragma(inline, true)
104-
void __release() @trusted nothrow {
105-
if (rc) {
106-
if (nu_atomic_sub_32(rc.refs, 1) == 1) {
107-
nogc_delete(rc.value);
108-
nu_free(rc);
109-
}
110-
}
111-
this.rc = null;
112-
}
113-
114-
public:
115-
alias value this;
116-
117-
/**
118-
The value stored in the rc type.
119-
*/
120-
@property T value() @safe => rc ? rc.value : T.init;
121+
struct __rc(T) {
122+
private:
123+
@nogc:
124+
uint refs;
125+
T value;
121126
}

tests/ut/rc.d

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@ import numem.lifetime : nogc_delete;
44

55
@("Rc!int")
66
unittest {
7-
Rc!int a = 24;
8-
assert(a == 24);
9-
10-
a.release();
11-
assert(a == 0);
12-
}
7+
__gshared size_t rct_objects = 1;
8+
static struct RCT1 {
9+
int v;
10+
alias v this;
1311

14-
@("Arc!int")
15-
unittest {
16-
Arc!int a = 24;
17-
assert(a == 24);
12+
~this() @nogc { rct_objects--; }
13+
this(ref return scope inout(typeof(this)) rhs) @nogc { rct_objects++; v = rhs.v; }
14+
this(int value) @nogc {
15+
rct_objects++;
16+
v = value;
17+
}
18+
}
19+
20+
Rc!RCT1 a = RCT1(42);
21+
assert(rct_objects == 1);
22+
assert(a.v == 42);
1823

19-
nogc_delete(a);
20-
assert(a == 0);
21-
}
24+
a.release();
25+
assert(rct_objects == 0);
26+
}

0 commit comments

Comments
 (0)