Skip to content

Commit 9319496

Browse files
authored
Merge pull request #1243 from cuviper/static_mut_refs
Fix `static_mut_refs` on the global registry
2 parents ce00470 + fade88f commit 9319496

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

rayon-core/src/registry.rs

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

@@ -189,8 +195,14 @@ where
189195
));
190196

191197
THE_REGISTRY_SET.call_once(|| {
192-
result = registry()
193-
.map(|registry: Arc<Registry>| unsafe { &*THE_REGISTRY.get_or_insert(registry) })
198+
result = registry().map(|registry: Arc<Registry>| {
199+
// SAFETY: this is the only mutable access to `THE_REGISTRY`, thanks to `Once`, and
200+
// `global_registry()` only takes a shared reference **after** this `call_once`.
201+
unsafe {
202+
ptr::addr_of_mut!(THE_REGISTRY).write(Some(registry));
203+
(*ptr::addr_of!(THE_REGISTRY)).as_ref().unwrap_unchecked()
204+
}
205+
})
194206
});
195207

196208
result

0 commit comments

Comments
 (0)