Skip to content

Commit 1c864b1

Browse files
committed
Replace unsafe static variables with thread-local storage, but still require cargo test -- --test-threads=1.
1 parent 48a19aa commit 1c864b1

File tree

2 files changed

+108
-104
lines changed

2 files changed

+108
-104
lines changed

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ jobs:
2525
- name: Build
2626
run: cargo build --verbose
2727
- name: Run tests
28-
run: cargo test --verbose
28+
run: cargo test --verbose -- --test-threads=1

macros/tests/dep.rs

Lines changed: 107 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,55 @@
11
#![allow(static_mut_refs)]
22

3+
use std::cell::Cell;
4+
35
use cache::Observable as _;
46
use macros::{memo, signal};
57

6-
static mut SOURCE_A_CALLED: bool = false;
7-
static mut SOURCE_B_CALLED: bool = false;
8-
static mut SOURCE_C_CALLED: bool = false;
9-
static mut SOURCE_D_CALLED: bool = false;
10-
static mut SOURCE_E_CALLED: bool = false;
8+
thread_local! {
9+
static SOURCE_A_CALLED: Cell<bool> = const { Cell::new(false) };
10+
static SOURCE_B_CALLED: Cell<bool> = const { Cell::new(false) };
11+
static SOURCE_C_CALLED: Cell<bool> = const { Cell::new(false) };
12+
static SOURCE_D_CALLED: Cell<bool> = const { Cell::new(false) };
13+
static SOURCE_E_CALLED: Cell<bool> = const { Cell::new(false) };
1114

12-
static mut A: i32 = 10;
13-
static mut B: i32 = 5;
15+
static A: Cell<i32> = const { Cell::new(10) };
16+
static B: Cell<i32> = const { Cell::new(5) };
17+
}
1418

1519
#[signal]
1620
pub fn source_a() -> i32 {
17-
unsafe { SOURCE_A_CALLED = true };
21+
SOURCE_A_CALLED.set(true);
1822

19-
unsafe { A }
23+
A.get()
2024
}
2125

2226
#[signal]
2327
pub fn source_b() -> i32 {
24-
unsafe { SOURCE_B_CALLED = true };
28+
SOURCE_B_CALLED.set(true);
2529

26-
unsafe { B }
30+
B.get()
2731
}
2832

2933
#[memo]
3034
pub fn derived_c() -> i32 {
31-
assert!(!unsafe { SOURCE_C_CALLED });
32-
unsafe { SOURCE_C_CALLED = true };
35+
assert!(!SOURCE_C_CALLED.get());
36+
SOURCE_C_CALLED.set(true);
3337

3438
source_a() + source_b()
3539
}
3640

3741
#[memo]
3842
pub fn derived_d() -> i32 {
39-
assert!(!unsafe { SOURCE_D_CALLED });
40-
unsafe { SOURCE_D_CALLED = true };
43+
assert!(!SOURCE_D_CALLED.get());
44+
SOURCE_D_CALLED.set(true);
4145

4246
derived_c() * 2
4347
}
4448

4549
#[memo]
4650
pub fn derived_e() -> i32 {
47-
assert!(!unsafe { SOURCE_E_CALLED });
48-
unsafe { SOURCE_E_CALLED = true };
51+
assert!(!SOURCE_E_CALLED.get());
52+
SOURCE_E_CALLED.set(true);
4953

5054
source_b() - 3
5155
}
@@ -58,78 +62,78 @@ pub fn derived_e() -> i32 {
5862

5963
#[test]
6064
fn complex_dependency_memo_test() {
61-
unsafe { SOURCE_A_CALLED = false };
62-
unsafe { SOURCE_B_CALLED = false };
63-
unsafe { SOURCE_C_CALLED = false };
64-
unsafe { SOURCE_D_CALLED = false };
65-
unsafe { SOURCE_E_CALLED = false };
65+
SOURCE_A_CALLED.set(false);
66+
SOURCE_B_CALLED.set(false);
67+
SOURCE_C_CALLED.set(false);
68+
SOURCE_D_CALLED.set(false);
69+
SOURCE_E_CALLED.set(false);
6670

6771
let e1 = derived_e();
68-
assert!(!unsafe { SOURCE_A_CALLED });
69-
assert!(unsafe { SOURCE_B_CALLED });
70-
assert!(!unsafe { SOURCE_C_CALLED });
71-
assert!(!unsafe { SOURCE_D_CALLED });
72-
assert!(unsafe { SOURCE_E_CALLED });
72+
assert!(!SOURCE_A_CALLED.get());
73+
assert!(SOURCE_B_CALLED.get());
74+
assert!(!SOURCE_C_CALLED.get());
75+
assert!(!SOURCE_D_CALLED.get());
76+
assert!(SOURCE_E_CALLED.get());
7377
let d1 = derived_d();
74-
assert!(unsafe { SOURCE_A_CALLED });
75-
assert!(unsafe { SOURCE_B_CALLED });
76-
assert!(unsafe { SOURCE_C_CALLED });
77-
assert!(unsafe { SOURCE_D_CALLED });
78-
assert!(unsafe { SOURCE_E_CALLED });
78+
assert!(SOURCE_A_CALLED.get());
79+
assert!(SOURCE_B_CALLED.get());
80+
assert!(SOURCE_C_CALLED.get());
81+
assert!(SOURCE_D_CALLED.get());
82+
assert!(SOURCE_E_CALLED.get());
7983
let c1 = derived_c();
8084

8185
assert_eq!(c1, 15); // 10 + 5
8286
assert_eq!(d1, 30); // 15 * 2
8387
assert_eq!(e1, 2); // 5 - 3
8488

85-
unsafe { A = 10 };
89+
A.set(10);
8690

87-
unsafe { SOURCE_A_CALLED = false };
88-
unsafe { SOURCE_B_CALLED = false };
89-
unsafe { SOURCE_C_CALLED = false };
90-
unsafe { SOURCE_D_CALLED = false };
91-
unsafe { SOURCE_E_CALLED = false };
91+
SOURCE_A_CALLED.set(false);
92+
SOURCE_B_CALLED.set(false);
93+
SOURCE_C_CALLED.set(false);
94+
SOURCE_D_CALLED.set(false);
95+
SOURCE_E_CALLED.set(false);
9296

9397
let e2 = derived_e();
9498
let d2 = derived_d();
9599
let c2 = derived_c();
96100

97-
assert!(!unsafe { SOURCE_A_CALLED });
98-
assert!(!unsafe { SOURCE_B_CALLED });
99-
assert!(!unsafe { SOURCE_C_CALLED });
100-
assert!(!unsafe { SOURCE_D_CALLED });
101-
assert!(!unsafe { SOURCE_E_CALLED });
101+
assert!(!SOURCE_A_CALLED.get());
102+
assert!(!SOURCE_B_CALLED.get());
103+
assert!(!SOURCE_C_CALLED.get());
104+
assert!(!SOURCE_D_CALLED.get());
105+
assert!(!SOURCE_E_CALLED.get());
102106

103107
assert_eq!(c2, c1);
104108
assert_eq!(d2, d1);
105109
assert_eq!(e2, e1);
106110

107111
unsafe { SOURCE_A.invalidate() };
108112

109-
unsafe { SOURCE_A_CALLED = false };
110-
unsafe { SOURCE_B_CALLED = false };
111-
unsafe { SOURCE_C_CALLED = false };
112-
unsafe { SOURCE_D_CALLED = false };
113-
unsafe { SOURCE_E_CALLED = false };
113+
SOURCE_A_CALLED.set(false);
114+
SOURCE_B_CALLED.set(false);
115+
SOURCE_C_CALLED.set(false);
116+
SOURCE_D_CALLED.set(false);
117+
SOURCE_E_CALLED.set(false);
114118

115119
let e3 = derived_e();
116-
assert!(!unsafe { SOURCE_A_CALLED });
117-
assert!(!unsafe { SOURCE_B_CALLED });
118-
assert!(!unsafe { SOURCE_C_CALLED });
119-
assert!(!unsafe { SOURCE_D_CALLED });
120-
assert!(!unsafe { SOURCE_E_CALLED });
120+
assert!(!SOURCE_A_CALLED.get());
121+
assert!(!SOURCE_B_CALLED.get());
122+
assert!(!SOURCE_C_CALLED.get());
123+
assert!(!SOURCE_D_CALLED.get());
124+
assert!(!SOURCE_E_CALLED.get());
121125
let d3 = derived_d();
122-
assert!(unsafe { SOURCE_A_CALLED });
123-
assert!(unsafe { SOURCE_B_CALLED });
124-
assert!(unsafe { SOURCE_C_CALLED });
125-
assert!(unsafe { SOURCE_D_CALLED });
126-
assert!(!unsafe { SOURCE_E_CALLED });
126+
assert!(SOURCE_A_CALLED.get());
127+
assert!(SOURCE_B_CALLED.get());
128+
assert!(SOURCE_C_CALLED.get());
129+
assert!(SOURCE_D_CALLED.get());
130+
assert!(!SOURCE_E_CALLED.get());
127131
let c3 = derived_c();
128-
assert!(unsafe { SOURCE_A_CALLED });
129-
assert!(unsafe { SOURCE_B_CALLED });
130-
assert!(unsafe { SOURCE_C_CALLED });
131-
assert!(unsafe { SOURCE_D_CALLED });
132-
assert!(!unsafe { SOURCE_E_CALLED });
132+
assert!(SOURCE_A_CALLED.get());
133+
assert!(SOURCE_B_CALLED.get());
134+
assert!(SOURCE_C_CALLED.get());
135+
assert!(SOURCE_D_CALLED.get());
136+
assert!(!SOURCE_E_CALLED.get());
133137

134138
assert_eq!(c3, 15);
135139
assert_eq!(d3, 30);
@@ -138,11 +142,11 @@ fn complex_dependency_memo_test() {
138142

139143
#[test]
140144
fn signal_set_unchanged_test() {
141-
unsafe { SOURCE_A_CALLED = false };
142-
unsafe { SOURCE_B_CALLED = false };
143-
unsafe { SOURCE_C_CALLED = false };
144-
unsafe { SOURCE_D_CALLED = false };
145-
unsafe { SOURCE_E_CALLED = false };
145+
SOURCE_A_CALLED.set(false);
146+
SOURCE_B_CALLED.set(false);
147+
SOURCE_C_CALLED.set(false);
148+
SOURCE_D_CALLED.set(false);
149+
SOURCE_E_CALLED.set(false);
146150

147151
let e1 = derived_e();
148152
let d1 = derived_d();
@@ -154,21 +158,21 @@ fn signal_set_unchanged_test() {
154158

155159
unsafe { SOURCE_A.set(10) };
156160

157-
unsafe { SOURCE_A_CALLED = false };
158-
unsafe { SOURCE_B_CALLED = false };
159-
unsafe { SOURCE_C_CALLED = false };
160-
unsafe { SOURCE_D_CALLED = false };
161-
unsafe { SOURCE_E_CALLED = false };
161+
SOURCE_A_CALLED.set(false);
162+
SOURCE_B_CALLED.set(false);
163+
SOURCE_C_CALLED.set(false);
164+
SOURCE_D_CALLED.set(false);
165+
SOURCE_E_CALLED.set(false);
162166

163167
let e2 = derived_e();
164168
let d2 = derived_d();
165169
let c2 = derived_c();
166170

167-
assert!(!unsafe { SOURCE_A_CALLED });
168-
assert!(!unsafe { SOURCE_B_CALLED });
169-
assert!(!unsafe { SOURCE_C_CALLED });
170-
assert!(!unsafe { SOURCE_D_CALLED });
171-
assert!(!unsafe { SOURCE_E_CALLED });
171+
assert!(!SOURCE_A_CALLED.get());
172+
assert!(!SOURCE_B_CALLED.get());
173+
assert!(!SOURCE_C_CALLED.get());
174+
assert!(!SOURCE_D_CALLED.get());
175+
assert!(!SOURCE_E_CALLED.get());
172176

173177
assert_eq!(c2, c1);
174178
assert_eq!(d2, d1);
@@ -177,11 +181,11 @@ fn signal_set_unchanged_test() {
177181

178182
#[test]
179183
fn signal_set_value_test() {
180-
unsafe { SOURCE_A_CALLED = false };
181-
unsafe { SOURCE_B_CALLED = false };
182-
unsafe { SOURCE_C_CALLED = false };
183-
unsafe { SOURCE_D_CALLED = false };
184-
unsafe { SOURCE_E_CALLED = false };
184+
SOURCE_A_CALLED.set(false);
185+
SOURCE_B_CALLED.set(false);
186+
SOURCE_C_CALLED.set(false);
187+
SOURCE_D_CALLED.set(false);
188+
SOURCE_E_CALLED.set(false);
185189

186190
let e1 = derived_e();
187191
let d1 = derived_d();
@@ -193,30 +197,30 @@ fn signal_set_value_test() {
193197

194198
unsafe { SOURCE_A.set(20) };
195199

196-
unsafe { SOURCE_A_CALLED = false };
197-
unsafe { SOURCE_B_CALLED = false };
198-
unsafe { SOURCE_C_CALLED = false };
199-
unsafe { SOURCE_D_CALLED = false };
200-
unsafe { SOURCE_E_CALLED = false };
200+
SOURCE_A_CALLED.set(false);
201+
SOURCE_B_CALLED.set(false);
202+
SOURCE_C_CALLED.set(false);
203+
SOURCE_D_CALLED.set(false);
204+
SOURCE_E_CALLED.set(false);
201205

202206
let e2 = derived_e();
203-
assert!(!unsafe { SOURCE_A_CALLED });
204-
assert!(!unsafe { SOURCE_B_CALLED });
205-
assert!(!unsafe { SOURCE_C_CALLED });
206-
assert!(!unsafe { SOURCE_D_CALLED });
207-
assert!(!unsafe { SOURCE_E_CALLED });
207+
assert!(!SOURCE_A_CALLED.get());
208+
assert!(!SOURCE_B_CALLED.get());
209+
assert!(!SOURCE_C_CALLED.get());
210+
assert!(!SOURCE_D_CALLED.get());
211+
assert!(!SOURCE_E_CALLED.get());
208212
let d2 = derived_d();
209-
assert!(unsafe { SOURCE_A_CALLED });
210-
assert!(unsafe { SOURCE_B_CALLED });
211-
assert!(unsafe { SOURCE_C_CALLED });
212-
assert!(unsafe { SOURCE_D_CALLED });
213-
assert!(!unsafe { SOURCE_E_CALLED });
213+
assert!(SOURCE_A_CALLED.get());
214+
assert!(SOURCE_B_CALLED.get());
215+
assert!(SOURCE_C_CALLED.get());
216+
assert!(SOURCE_D_CALLED.get());
217+
assert!(!SOURCE_E_CALLED.get());
214218
let c2 = derived_c();
215-
assert!(unsafe { SOURCE_A_CALLED });
216-
assert!(unsafe { SOURCE_B_CALLED });
217-
assert!(unsafe { SOURCE_C_CALLED });
218-
assert!(unsafe { SOURCE_D_CALLED });
219-
assert!(!unsafe { SOURCE_E_CALLED });
219+
assert!(SOURCE_A_CALLED.get());
220+
assert!(SOURCE_B_CALLED.get());
221+
assert!(SOURCE_C_CALLED.get());
222+
assert!(SOURCE_D_CALLED.get());
223+
assert!(!SOURCE_E_CALLED.get());
220224

221225
assert_eq!(c2, c1);
222226
assert_eq!(d2, d1);

0 commit comments

Comments
 (0)