Use ManuallyDrop to allow non-Copy T
- Dominant language
- Rust
- Stars
- 40
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
I'm working with Slint, and it doesn't allow multithreading UI stuff (ie. the types are not Send) and yet it requires all callbacks to be `'static`, which was quite a conundrum. The easy solution is to use a thread_local static, but that doesn't feel right. I found this crate and I wanted to store my data as a static `LazyLock>`, but it turns out that isn't allowed because App isn't Copy. I ended up with this custom thing inspired by it:
```rust
pub struct ThreadChecked {
value: ManuallyDrop,
thread_id: ThreadId
}
impl ThreadChecked {
pub fn new(value: T) -> Self {
Self {
value: ManuallyDrop::new(value),
thread_id: std::thread::current().id()
}
}
fn check(&self) {
if std::thread::current().id() != self.thread_id {
panic!("{} value was accessed from the wrong thread", type_name::());
}
}
}
unsafe impl Send for ThreadChecked {}
unsafe impl Sync for ThreadChecked {}
impl Default for ThreadChecked {
fn default() -> Self {
Self::new(Default::default())
}
}
impl Drop for ThreadChecked {
fn drop(&mut self) {
if std::thread::current().id() != self.thread_id {
panic!("{} value was dropped from the wrong thread, leaking it!", type_name::());
} else {
unsafe {
ManuallyDrop::drop(&mut self.value);
}
}
}
}
impl Deref for ThreadChecked {
type Target = T;
fn deref(&self) -> &T {
self.check();
&self.value
}
}
impl DerefMut for ThreadChecked {
fn deref_mut(&mut self) -> &mut T {
self.check();
&mut self.value
}
}
```
See, Rust allows you to simply not drop values if you don't want to, so you can safely just use ManuallyDrop to prevent drop from being called in the wrong thread. I also added a panic there to mitigate the danger of the value being leaked silently. My suggestion is that this crate do the same thing so it can drop the Copy restriction and be useful in more cases.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.