Add Sync/Send wrapper for main-thread-only data

This commit is contained in:
Mahmoud Al-Qudsi 2024-02-28 13:06:04 -06:00
parent 29af775390
commit f67ce2ac4b

View File

@ -4,6 +4,8 @@
use crate::flog::{FloggableDebug, FLOG}; use crate::flog::{FloggableDebug, FLOG};
use crate::reader::ReaderData; use crate::reader::ReaderData;
use once_cell::race::OnceBox; use once_cell::race::OnceBox;
use std::cell::RefCell;
use std::marker::PhantomData;
use std::num::NonZeroU64; use std::num::NonZeroU64;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -358,6 +360,44 @@ impl ThreadPool {
} }
} }
/// A `Sync` and `Send` wrapper for non-`Sync`/`Send` types.
/// Only allows access from the main thread.
pub struct MainThread<T> {
data: RefCell<T>,
// Make type !Send and !Sync by default
_marker: PhantomData<*const ()>,
}
// Manually implement Send and Sync for MainThread<T> to ensure it can be shared across threads
// as long as T is 'static.
unsafe impl<T: 'static> Send for MainThread<T> {}
unsafe impl<T: 'static> Sync for MainThread<T> {}
impl<T> MainThread<T> {
pub const fn new(value: T) -> Self {
Self {
data: RefCell::new(value),
_marker: PhantomData,
}
}
pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
assert_is_main_thread();
f(&self.data.borrow())
}
pub fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
assert_is_main_thread();
f(&mut self.data.borrow_mut())
}
}
pub struct WorkerThread { pub struct WorkerThread {
/// The data shared with the [`ThreadPool`]. /// The data shared with the [`ThreadPool`].
shared: Arc<ThreadPoolShared>, shared: Arc<ThreadPoolShared>,