From f67ce2ac4b2a5088703d3da99edb4b913e4bccf4 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Wed, 28 Feb 2024 13:06:04 -0600 Subject: [PATCH] Add Sync/Send wrapper for main-thread-only data --- src/threads.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/threads.rs b/src/threads.rs index f0c80e01d..0e7c7905c 100644 --- a/src/threads.rs +++ b/src/threads.rs @@ -4,6 +4,8 @@ use crate::flog::{FloggableDebug, FLOG}; use crate::reader::ReaderData; use once_cell::race::OnceBox; +use std::cell::RefCell; +use std::marker::PhantomData; use std::num::NonZeroU64; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; @@ -358,6 +360,44 @@ fn spawn_thread(&mut self) -> bool { } } +/// A `Sync` and `Send` wrapper for non-`Sync`/`Send` types. +/// Only allows access from the main thread. +pub struct MainThread { + data: RefCell, + // Make type !Send and !Sync by default + _marker: PhantomData<*const ()>, +} + +// Manually implement Send and Sync for MainThread to ensure it can be shared across threads +// as long as T is 'static. +unsafe impl Send for MainThread {} +unsafe impl Sync for MainThread {} + +impl MainThread { + pub const fn new(value: T) -> Self { + Self { + data: RefCell::new(value), + _marker: PhantomData, + } + } + + pub fn with(&self, f: F) -> R + where + F: FnOnce(&T) -> R, + { + assert_is_main_thread(); + f(&self.data.borrow()) + } + + pub fn with_mut(&self, f: F) -> R + where + F: FnOnce(&mut T) -> R, + { + assert_is_main_thread(); + f(&mut self.data.borrow_mut()) + } +} + pub struct WorkerThread { /// The data shared with the [`ThreadPool`]. shared: Arc,