vulkayes_core/util/
sync.rs

1//! This module contains type aliases and wrappers to make switching `multi_thread` feature seamless.
2
3pub use inner::*;
4
5// IDEA: Consider adding Vrc<T> = ManuallyDrop<T> as an unsafe alternative
6
7#[macro_use]
8#[cfg(feature = "multi_thread")]
9mod inner {
10	/// Expands the tokens and adds `+ Send + Sync` at the end.
11	///
12	/// This can be used to conditionally add `Send + Sync` bounds to types when the `multi_thread` feature is enabled.
13	#[macro_export]
14	macro_rules! VSendSync {
15		(
16			$($ts: tt)+
17		) => {
18			$($ts)+ + Send + Sync
19		}
20	}
21
22	/// A type alias to `Arc`.
23	pub type Vrc<T> = std::sync::Arc<T>;
24	/// A type alias to `AtomicBool`.
25	pub type AtomicVool = std::sync::atomic::AtomicBool;
26
27	#[cfg(feature = "parking_lot_vutex")]
28	mod vutex {
29		/// A type alias to `parking_lot::Mutex`.
30		pub type Vutex<T> = parking_lot::Mutex<T>;
31		/// A type alias to `parking_lot::MutexGuard`.
32		pub type VutexGuard<'a, T> = parking_lot::MutexGuard<'a, T>;
33	}
34	#[cfg(not(feature = "parking_lot_vutex"))]
35	mod vutex {
36		/// A type alias to `Mutex`.
37		pub type Vutex<T> = std::sync::Mutex<T>;
38		/// A type alias to `MutexGuard`.
39		pub type VutexGuard<'a, T> = std::sync::MutexGuard<'a, T>;
40	}
41	pub use vutex::*;
42}
43
44#[macro_use]
45#[cfg(not(feature = "multi_thread"))]
46mod inner {
47	use std::cell::{BorrowMutError, Cell, RefCell, RefMut};
48
49	/// Does nothing.
50	///
51	/// This is provided as a single-thread alternative to the `VSendSync` macro,
52	/// which adds `Send + Sync` bounds to types when the `multi_thread` feature is enabled.
53	#[macro_export]
54	macro_rules! VSendSync {
55		(
56			$($ts: tt)+
57		) => {
58			$($ts)+
59		}
60	}
61
62	/// A type alias to `Rc`.
63	pub type Vrc<T> = std::rc::Rc<T>;
64	/// A type that is interface-compatible with `AtomicBool` to be used in single-threaded context.
65	pub struct AtomicVool(pub std::cell::Cell<bool>);
66	impl AtomicVool {
67		pub const fn new(value: bool) -> Self {
68			AtomicVool(Cell::new(value))
69		}
70
71		pub fn load(&self, _: std::sync::atomic::Ordering) -> bool {
72			self.0.get()
73		}
74
75		pub fn store(&self, value: bool, _: std::sync::atomic::Ordering) {
76			self.0.set(value)
77		}
78
79		pub fn swap(&self, value: bool, _: std::sync::atomic::Ordering) -> bool {
80			self.0.replace(value)
81		}
82	}
83
84	/// Type that is interface-compatible with `Mutex` to be used in single-threaded context.
85	///
86	/// This type is treated as "poisoned" when it is attempted to lock it twice.
87	#[derive(Debug)]
88	#[repr(transparent)]
89	pub struct Vutex<T>(pub RefCell<T>);
90	impl<T> Vutex<T> {
91		pub const fn new(value: T) -> Self {
92			Vutex(RefCell::new(value))
93		}
94
95		pub fn lock(&self) -> Result<VutexGuard<T>, BorrowMutError> {
96			self.0.try_borrow_mut()
97		}
98	}
99	/// Type that is `Deref`-compatible with `MutexGuard` in single-thread context.
100	pub type VutexGuard<'a, T> = RefMut<'a, T>;
101}
102
103#[macro_use]
104#[cfg(feature = "multi_thread")]
105mod test {
106	#[allow(unused_imports)] // It is actually used
107	use crate::prelude::Vrc;
108
109	macro_rules! test_send_sync {
110		(
111			$(
112				$name: ident: $test_type: ty
113			),+
114		) => {
115			$(
116				#[test]
117				fn $name() {
118					fn accepts_send_sync(_any: impl Send + Sync) {}
119
120					accepts_send_sync(
121						std::mem::MaybeUninit::<$test_type>::uninit()
122					);
123				}
124			)+
125		}
126	}
127
128	// These are compile-time tests to check correct trait properties
129	// These test "fail" when they don't compile
130	test_send_sync!(
131		instance_send_sync: Vrc<crate::instance::Instance>,
132		device_send_sync: Vrc<crate::device::Device>,
133		queue_send_sync: Vrc<crate::queue::Queue>,
134		//
135		fence_send_sync: Vrc<crate::sync::fence::Fence>,
136		semaphore_send_sync: Vrc<crate::sync::semaphore::Semaphore>,
137		binary_semaphore_send_sync: Vrc<crate::sync::semaphore::BinarySemaphore>,
138		//
139		swapchain_send_sync: Vrc<crate::swapchain::Swapchain>,
140		swapchain_image_send_sync: Vrc<crate::swapchain::image::SwapchainImage>,
141		//
142		image_send_sync: Vrc<crate::resource::image::Image>,
143		image_view_send_sync: Vrc<crate::resource::image::view::ImageView>,
144		buffer_send_sync: Vrc<crate::resource::buffer::Buffer>,
145		buffer_view_send_sync: Vrc<crate::resource::buffer::view::BufferView>,
146		//
147		command_pool_send_sync: Vrc<crate::command::pool::CommandPool>,
148		command_buffer_send_sync: Vrc<crate::command::buffer::CommandBuffer>,
149		//
150		descriptor_set_layout_send_sync: Vrc<crate::descriptor::layout::DescriptorSetLayout>,
151		pipeline_layout_send_sync: Vrc<crate::pipeline::layout::PipelineLayout>,
152		//
153		descriptor_pool_send_sync: Vrc<crate::descriptor::pool::DescriptorPool>,
154		descriptor_set_send_sync: Vrc<crate::descriptor::set::DescriptorSet>
155	);
156}