Move FromDyn closer to is_dyn_thread_safe

This commit is contained in:
Daria Sukhonina
2026-03-12 14:51:08 +03:00
parent b711f95f86
commit 15f42e2613
2 changed files with 50 additions and 48 deletions
@@ -188,53 +188,6 @@ pub fn assert_dyn_send<T: ?Sized + PointeeSized + DynSend>() {}
pub fn assert_dyn_send_val<T: ?Sized + PointeeSized + DynSend>(_t: &T) {}
pub fn assert_dyn_send_sync_val<T: ?Sized + PointeeSized + DynSync + DynSend>(_t: &T) {}
#[derive(Copy, Clone)]
pub struct FromDyn<T>(T);
impl<T> FromDyn<T> {
#[inline(always)]
pub fn from(val: T) -> Self {
// Check that `sync::is_dyn_thread_safe()` is true on creation so we can
// implement `Send` and `Sync` for this structure when `T`
// implements `DynSend` and `DynSync` respectively.
assert!(crate::sync::is_dyn_thread_safe());
FromDyn(val)
}
#[inline(always)]
pub fn derive<O>(&self, val: O) -> FromDyn<O> {
// We already did the check for `sync::is_dyn_thread_safe()` when creating `Self`
FromDyn(val)
}
#[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
}
// `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
unsafe impl<T: DynSend> Send for FromDyn<T> {}
// `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
unsafe impl<T: DynSync> Sync for FromDyn<T> {}
impl<T> std::ops::Deref for FromDyn<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> std::ops::DerefMut for FromDyn<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
// A wrapper to convert a struct that is already a `Send` or `Sync` into
// an instance of `DynSend` and `DynSync`, since the compiler cannot infer
// it automatically in some cases. (e.g. Box<dyn Send / Sync>)
+50 -1
View File
@@ -34,7 +34,7 @@
pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
#[doc(no_inline)]
pub use self::lock::{Lock, LockGuard, Mode};
pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
pub use self::mode::{is_dyn_thread_safe, FromDyn, set_dyn_thread_safe_mode};
pub use self::parallel::{
broadcast, par_fns, par_for_each_in, par_join, par_map, parallel_guard, spawn,
try_par_for_each_in,
@@ -64,6 +64,8 @@ mod atomic {
mod mode {
use std::sync::atomic::{AtomicU8, Ordering};
use crate::sync::{DynSend, DynSync};
const UNINITIALIZED: u8 = 0;
const DYN_NOT_THREAD_SAFE: u8 = 1;
const DYN_THREAD_SAFE: u8 = 2;
@@ -99,6 +101,53 @@ pub fn set_dyn_thread_safe_mode(mode: bool) {
// Check that the mode was either uninitialized or was already set to the requested mode.
assert!(previous.is_ok() || previous == Err(set));
}
#[derive(Copy, Clone)]
pub struct FromDyn<T>(T);
impl<T> FromDyn<T> {
#[inline(always)]
pub fn from(val: T) -> Self {
// Check that `sync::is_dyn_thread_safe()` is true on creation so we can
// implement `Send` and `Sync` for this structure when `T`
// implements `DynSend` and `DynSync` respectively.
assert!(crate::sync::is_dyn_thread_safe());
FromDyn(val)
}
#[inline(always)]
pub fn derive<O>(&self, val: O) -> FromDyn<O> {
// We already did the check for `sync::is_dyn_thread_safe()` when creating `Self`
FromDyn(val)
}
#[inline(always)]
pub fn into_inner(self) -> T {
self.0
}
}
// `FromDyn` is `Send` if `T` is `DynSend`, since it ensures that sync::is_dyn_thread_safe() is true.
unsafe impl<T: DynSend> Send for FromDyn<T> {}
// `FromDyn` is `Sync` if `T` is `DynSync`, since it ensures that sync::is_dyn_thread_safe() is true.
unsafe impl<T: DynSync> Sync for FromDyn<T> {}
impl<T> std::ops::Deref for FromDyn<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> std::ops::DerefMut for FromDyn<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
}
/// This makes locks panic if they are already held.