From a905439d9cf5eb4c9f523d7858e44b9e7235113f Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 7 Dec 2020 14:58:59 -0600 Subject: [PATCH] Add strategic backoff in WinRT backend to (hopefully) eliminate a deadlock. --- Cargo.toml | 1 + src/backends/winrt.rs | 30 ++++++++++++++++++++++-------- src/lib.rs | 8 ++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7d4f78b..6e1eb71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ crate-type = ["lib", "cdylib", "staticlib"] use_tolk = ["tolk"] [dependencies] +backoff = "0.2" dyn-clonable = "0.9" lazy_static = "1" log = "0.4" diff --git a/src/backends/winrt.rs b/src/backends/winrt.rs index 512eba4..4e60abe 100644 --- a/src/backends/winrt.rs +++ b/src/backends/winrt.rs @@ -1,7 +1,8 @@ -#[cfg(windows)] -use std::collections::HashMap; use std::sync::Mutex; +#[cfg(windows)] +use std::{collections::HashMap, time::Duration}; +use backoff::{ExponentialBackoff, Operation}; use lazy_static::lazy_static; use log::{info, trace}; use winrt::*; @@ -133,6 +134,13 @@ impl WinRT { playback_list, }) } + + fn backoff(&self) -> ExponentialBackoff { + ExponentialBackoff { + initial_interval: Duration::from_millis(3), + ..Default::default() + } + } } impl Backend for WinRT { @@ -167,12 +175,18 @@ impl Backend for WinRT { if self.player.playback_session()?.playback_state()? != MediaPlaybackState::Playing { self.player.play()?; } - let mut uid = NEXT_UTTERANCE_ID.lock().unwrap(); - let utterance_id = UtteranceId::WinRT(*uid); - *uid += 1; - drop(uid); - let mut mappings = UTTERANCE_MAPPINGS.lock().unwrap(); - mappings.push((self.id, item, utterance_id)); + let mut op = || { + let mut uid = NEXT_UTTERANCE_ID.try_lock()?; + let utterance_id = UtteranceId::WinRT(*uid); + *uid += 1; + Ok(utterance_id) + }; + let mut backoff = self.backoff(); + let utterance_id = op.retry(&mut backoff)?; + { + let mut mappings = UTTERANCE_MAPPINGS.lock().unwrap(); + mappings.push((self.id, item, utterance_id)); + } Ok(Some(utterance_id)) } diff --git a/src/lib.rs b/src/lib.rs index 820ccd3..15504f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,6 +99,8 @@ impl Default for Features { pub enum Error { #[error("IO error: {0}")] IO(#[from] std::io::Error), + #[error("Backoff error")] + Backoff, #[error("Value not received")] NoneError, #[cfg(target_arch = "wasm32")] @@ -113,6 +115,12 @@ pub enum Error { OutOfRange, } +impl From> for Error { + fn from(_: backoff::Error) -> Self { + Error::Backoff + } +} + #[clonable] trait Backend: Clone + std::fmt::Debug { fn id(&self) -> Option;