diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d1c11ef --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +# 0.1.4 + +- Improve perfomance by using [parking_lot](https://github.com/Amanieu/parking_lot) instead of OS mutexes. See https://webkit.org/blog/6161/locking-in-webkit/. diff --git a/Cargo.toml b/Cargo.toml index 0d92c46..32d4bf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "kittyaudio" description = "An audio playback library focusing on simplicity" license = "MIT OR BSL-1.0" -version = "0.1.3" +version = "0.1.4" exclude = ["assets/**"] documentation = "https://docs.rs/kittyaudio" homepage = "https://github.com/zeozeozeo/kittyaudio" @@ -17,6 +17,7 @@ readme = "README.md" [dependencies] cpal = { version = "0.15.2", optional = true } log = "0.4.20" +parking_lot = "0.12.1" serde = { version = "1.0.193", features = ["derive"], optional = true } symphonia = { version = "0.5.3", features = ["all"], optional = true } thiserror = "1.0.50" diff --git a/src/backend.rs b/src/backend.rs index 770ff93..6d2fb5f 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,15 +1,10 @@ -use std::sync::Arc; -use std::sync::Mutex; -use std::sync::PoisonError; -use std::time::Duration; - -use crate::KaError; -use crate::Renderer; -use crate::RendererHandle; +use crate::{KaError, Renderer, RendererHandle}; use cpal::{ traits::{DeviceTrait, HostTrait, StreamTrait}, FromSample, SampleFormat, SizedSample, StreamConfig, }; +use parking_lot::Mutex; +use std::{sync::Arc, time::Duration}; /// Specifies what device [`cpal`] should use. /// @@ -164,11 +159,7 @@ impl Backend { /// Handle all errors in the error queue. #[inline] pub fn handle_errors(&mut self, err_fn: impl FnMut(cpal::StreamError)) { - self.error_queue - .lock() - .unwrap_or_else(PoisonError::into_inner) - .drain(..) - .for_each(err_fn) + self.error_queue.lock().drain(..).for_each(err_fn) } /// Starts the audio thread. @@ -260,11 +251,7 @@ impl Backend { ) -> bool { // check for device disconnection let error_queue = self.error_queue.clone(); - for err in error_queue - .lock() - .unwrap_or_else(PoisonError::into_inner) - .drain(..) - { + for err in error_queue.lock().drain(..) { if matches!(err, cpal::StreamError::DeviceNotAvailable) { return true; } @@ -332,10 +319,7 @@ impl Backend { }, move |err| { // we got an error on stream, push it to the error queue - error_queue - .lock() - .unwrap_or_else(PoisonError::into_inner) - .push(err) + error_queue.lock().push(err) }, None, )?; diff --git a/src/mixer.rs b/src/mixer.rs index 303de03..e5734c9 100644 --- a/src/mixer.rs +++ b/src/mixer.rs @@ -6,7 +6,8 @@ use crate::Sound; #[cfg(feature = "cpal")] use crate::{Backend, Device, StreamSettings}; -use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; +use parking_lot::{Mutex, MutexGuard}; +use std::sync::Arc; /// The audio renderer trait. Can be used to make custom audio renderers. pub trait Renderer: Clone + Send + 'static { @@ -44,8 +45,8 @@ impl Renderer for DefaultRenderer { let mut out = Frame::ZERO; // remove all sounds that finished playback - self.sounds.retain_mut(|s| { - let mut guard = s.guard(); + self.sounds.retain_mut(|sound| { + let mut guard = sound.guard(); out += guard.next_frame(sample_rate); !guard.finished() }); @@ -73,7 +74,7 @@ impl RendererHandle { /// Get a lock on the underlying renderer. #[inline(always)] pub fn guard(&self) -> MutexGuard<'_, R> { - self.0.lock().unwrap_or_else(PoisonError::into_inner) + self.0.lock() } } @@ -108,7 +109,7 @@ impl Mixer { #[cfg(feature = "cpal")] #[inline(always)] pub fn backend(&self) -> MutexGuard<'_, Backend> { - self.backend.lock().unwrap_or_else(PoisonError::into_inner) + self.backend.lock() } /// Play a [`Sound`]. @@ -149,7 +150,6 @@ impl Mixer { // TODO: handle errors from `start_audio_thread` let _ = backend .lock() - .unwrap_or_else(PoisonError::into_inner) .start_audio_thread(device, settings, renderer); }); } diff --git a/src/sound.rs b/src/sound.rs index 8d2810e..e2903ee 100644 --- a/src/sound.rs +++ b/src/sound.rs @@ -1,7 +1,8 @@ use crate::{lerp_f64, Change, Command, Parameter, Resampler, Tweenable}; +use parking_lot::{Mutex, MutexGuard}; use std::ops::{Add, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}; use std::ops::{AddAssign, RangeInclusive}; -use std::sync::{Arc, Mutex, MutexGuard, PoisonError}; +use std::sync::Arc; use std::time::Duration; #[cfg(feature = "symphonia")] @@ -829,7 +830,7 @@ impl SoundHandle { /// Get a lock on the underlying [`Sound`]. #[inline] pub fn guard(&self) -> MutexGuard<'_, Sound> { - self.0.lock().unwrap_or_else(PoisonError::into_inner) + self.0.lock() } /// Return the sample rate of the sound.