Skip to content

Commit 03fb00f

Browse files
committed
Fix static_mut_refs on the global registry
(cherry picked from commit fade88f)
1 parent 6f13930 commit 03fb00f

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

rayon-core/src/registry.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,13 @@ static THE_REGISTRY_SET: Once = Once::new();
166166
/// configuration.
167167
pub(super) fn global_registry() -> &'static Arc<Registry> {
168168
set_global_registry(default_global_registry)
169-
.or_else(|err| unsafe { THE_REGISTRY.as_ref().ok_or(err) })
169+
.or_else(|err| {
170+
// SAFETY: we only create a shared reference to `THE_REGISTRY` after the `call_once`
171+
// that initializes it, and there will be no more mutable accesses at all.
172+
debug_assert!(THE_REGISTRY_SET.is_completed());
173+
let the_registry = unsafe { &*ptr::addr_of!(THE_REGISTRY) };
174+
the_registry.as_ref().ok_or(err)
175+
})
170176
.expect("The global thread pool has not been initialized.")
171177
}
172178

@@ -192,8 +198,14 @@ where
192198
));
193199

194200
THE_REGISTRY_SET.call_once(|| {
195-
result = registry()
196-
.map(|registry: Arc<Registry>| unsafe { &*THE_REGISTRY.get_or_insert(registry) })
201+
result = registry().map(|registry: Arc<Registry>| {
202+
// SAFETY: this is the only mutable access to `THE_REGISTRY`, thanks to `Once`, and
203+
// `global_registry()` only takes a shared reference **after** this `call_once`.
204+
unsafe {
205+
ptr::addr_of_mut!(THE_REGISTRY).write(Some(registry));
206+
(*ptr::addr_of!(THE_REGISTRY)).as_ref().unwrap_unchecked()
207+
}
208+
})
197209
});
198210

199211
result

0 commit comments

Comments
 (0)