From 2d5083fc763ca12a721b98e4b6461d555fa00a4c Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Thu, 21 Nov 2024 11:57:50 +0000 Subject: [PATCH 1/2] FBox should be Send and Sync if its contents is. This matches how a std::boxed::Box works. --- src/cpp/fbox.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cpp/fbox.rs b/src/cpp/fbox.rs index c082d7c5..24727341 100644 --- a/src/cpp/fbox.rs +++ b/src/cpp/fbox.rs @@ -25,6 +25,15 @@ impl std::fmt::Debug for FBox { } } +// SAFETY: An `FBox` owns its contents, so it is safe to move between threads if and only if the +// contents is safe to move between threads. This matches the behaviour of `std::boxed::Box`. +unsafe impl Send for FBox {} + +// SAFETY: An `FBox` derefs to its contents, so it is safe to pass an `&FBox` between threads if +// and only if it is safe to pass a reference to its contents between threads. This matches the +// behaviour of `std::boxed::Box`. +unsafe impl Sync for FBox {} + impl FBox { pub(crate) fn new(ptr: *mut T) -> Option { NonNull::new(ptr).map(FBox) From f47ccc9bf03842f8f9380a26d53bc6ecb0b0b675 Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Thu, 21 Nov 2024 12:03:39 +0000 Subject: [PATCH 2/2] Make various sound-related types Send and Sync. Music, Sound, SoundRecorderDriver and SoundBufferRecorder should be both Send and Sync. --- src/audio/capture.rs | 19 +++++++++++++++++++ src/audio/music.rs | 7 +++++++ src/audio/sound.rs | 7 +++++++ 3 files changed, 33 insertions(+) diff --git a/src/audio/capture.rs b/src/audio/capture.rs index 66a68938..3414343c 100644 --- a/src/audio/capture.rs +++ b/src/audio/capture.rs @@ -96,6 +96,15 @@ pub struct SoundRecorderDriver<'a, R: 'a> { recorder: &'a mut R, } +// SAFETY: An `sfCustomSoundRecorder` isn't tied to a particular thread, so it can be sent between +// threads safely. +unsafe impl Send for SoundRecorderDriver<'_, R> {} + +// SAFETY: An `&SoundRecorderDriver` only allows access to methods which read the status of the +// driver, which is fine to do from multiple threads at once. Thus it is safe to pass +// `&SoundRecorderDriver` between threads. +unsafe impl Sync for SoundRecorderDriver<'_, R> {} + unsafe extern "C" fn on_start_callback(user_data: *mut c_void) -> bool { let recorder: *mut R = user_data.cast(); unsafe { (*recorder).on_start() } @@ -246,6 +255,16 @@ pub struct SoundBufferRecorder { handle: NonNull, } +// SAFETY: An `sfSoundBufferRecorder` isn't tied to a particular thread, so it can be sent between +// threads safely. +unsafe impl Send for SoundBufferRecorder {} + +// SAFETY: An `&SoundBufferRecorder` only allows access to methods which read the status of the +// recorder, which is fine to do from multiple threads at once. Thus it is safe to pass +// `&SoundBufferRecorder` between threads. +unsafe impl Sync for SoundBufferRecorder {} + + impl SoundBufferRecorder { /// Create a new sound buffer recorder /// diff --git a/src/audio/music.rs b/src/audio/music.rs index 21cb8813..82b2aff0 100644 --- a/src/audio/music.rs +++ b/src/audio/music.rs @@ -38,6 +38,13 @@ pub struct Music<'src> { _stream: PhantomData<&'src mut ()>, } +// SAFETY: An `sfMusic` isn't tied to a particular thread, so it can be sent between threads safely. +unsafe impl Send for Music<'_> {} + +// SAFETY: An `&Music` only allows access to methods which read the status of the music, which is +// fine to do from multiple threads at once. Thus it is safe to pass `&Music` between threads. +unsafe impl Sync for Music<'_> {} + /// Creating and opening impl<'src> Music<'src> { /// Create a new (empty) `Music`. diff --git a/src/audio/sound.rs b/src/audio/sound.rs index b9777962..c0c8eebd 100644 --- a/src/audio/sound.rs +++ b/src/audio/sound.rs @@ -35,6 +35,13 @@ pub struct Sound<'buf> { buffer: PhantomData<&'buf SoundBuffer>, } +// SAFETY: An `sfSound` isn't tied to a particular thread, so it can be sent between threads safely. +unsafe impl Send for Sound<'_> {} + +// SAFETY: An `&Sound` only allows access to methods which read the status of the sound, which is +// fine to do from multiple threads at once. Thus it is safe to pass `&Sound` between threads. +unsafe impl Sync for Sound<'_> {} + /// Creation impl<'buf> Sound<'buf> { /// Create a new `Sound`