Skip to content

Commit 4f5406d

Browse files
Add new ref counted types Rc and Arc
1 parent c5eb010 commit 4f5406d

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

source/numem/package.d

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public import numem.casting;
1717
public import numem.lifetime;
1818
public import numem.object;
1919
public import numem.optional;
20+
public import numem.rc;
2021

2122
/**
2223
Container for numem version.

source/numem/rc.d

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/**
2+
Numem Rc Type
3+
4+
Copyright:
5+
Copyright © 2023-2025, Kitsunebi Games
6+
Copyright © 2023-2025, Inochi2D Project
7+
8+
License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
9+
Authors: Luna Nielsen
10+
*/
11+
module numem.rc;
12+
import numem.core.hooks;
13+
import numem.lifetime;
14+
15+
/**
16+
A reference counted container.
17+
*/
18+
struct Rc(T) {
19+
public:
20+
@nogc:
21+
mixin RcBase!T;
22+
23+
/**
24+
Creates an reference counted object using given $(D value).
25+
26+
Params:
27+
value = The value.
28+
*/
29+
this(T value) @trusted {
30+
this.rc = nogc_new!__rc(1, value);
31+
}
32+
}
33+
34+
/**
35+
Automatically reference counted value.
36+
*/
37+
struct Arc(T) {
38+
public:
39+
@nogc:
40+
mixin RcBase!T;
41+
42+
/// Destructor
43+
~this() {
44+
this.release();
45+
}
46+
47+
/**
48+
Creates an reference counted object using given $(D value).
49+
50+
Params:
51+
value = The value.
52+
*/
53+
this(T value) @trusted {
54+
this.rc = nogc_new!__rc(1, value);
55+
}
56+
57+
/**
58+
Copy constructor
59+
*/
60+
this(ref return scope inout(typeof(this)) rhs) inout @trusted {
61+
this.rc = rhs.rc;
62+
}
63+
}
64+
65+
// Base RefCounted.
66+
private mixin template RcBase(T) {
67+
private:
68+
@nogc:
69+
static struct __rc {
70+
private:
71+
@nogc:
72+
uint refs;
73+
T value;
74+
}
75+
76+
__rc* rc;
77+
public:
78+
alias value this;
79+
80+
/**
81+
The value stored in the rc type.
82+
*/
83+
@property T value() @safe => rc ? rc.value : T.init;
84+
85+
/**
86+
Retains a reference to the stored value.
87+
*/
88+
auto ref retain()() @trusted {
89+
if (rc) {
90+
nu_atomic_add_32(rc.refs, 1);
91+
}
92+
return this;
93+
}
94+
95+
/**
96+
Releases a reference to the stored value.
97+
This invalidates the Rc instance.
98+
*/
99+
auto ref release()() @trusted {
100+
if (rc) {
101+
if (nu_atomic_sub_32(rc.refs, 1) == 1) {
102+
nogc_delete(rc.value);
103+
nu_free(rc);
104+
}
105+
}
106+
this.rc = null;
107+
}
108+
}

tests/ut/rc.d

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module tests.ut.rc;
2+
import numem.rc;
3+
4+
@("Rc!int")
5+
unittest {
6+
Rc!int a = 24;
7+
assert(a == 24);
8+
9+
a.release();
10+
assert(a == 0);
11+
}
12+
13+
@("Arc!int")
14+
unittest {
15+
Arc!int a = 24;
16+
assert(a == 24);
17+
18+
a.release();
19+
assert(a == 0);
20+
}

0 commit comments

Comments
 (0)