@@ -470,29 +470,30 @@ impl AudioContext {
470
470
///
471
471
/// * The audio device is not available
472
472
/// * For a `BackendSpecificError`
473
- #[ allow( clippy:: await_holding_lock) ] // false positive due to explicit drop
474
473
pub async fn resume ( & self ) {
475
- // Lock the backend manager mutex to avoid concurrent calls
476
- log:: debug!( "Resume called, locking backend manager" ) ;
477
- let backend_manager_guard = self . backend_manager . lock ( ) . unwrap ( ) ;
474
+ let ( sender, receiver) = oneshot:: channel ( ) ;
478
475
479
- if self . state ( ) != AudioContextState :: Suspended {
480
- log :: debug! ( "Resume no-op - context is not suspended" ) ;
481
- return ;
482
- }
476
+ {
477
+ // Lock the backend manager mutex to avoid concurrent calls
478
+ log :: debug! ( "Resume called, locking backend manager" ) ;
479
+ let backend_manager_guard = self . backend_manager . lock ( ) . unwrap ( ) ;
483
480
484
- // Ask the audio host to resume the stream
485
- backend_manager_guard. resume ( ) ;
481
+ if self . state ( ) != AudioContextState :: Suspended {
482
+ log:: debug!( "Resume no-op - context is not suspended" ) ;
483
+ return ;
484
+ }
486
485
487
- // Then, ask to resume rendering via a control message
488
- log:: debug!( "Resumed audio stream, waking audio graph" ) ;
489
- let ( sender, receiver) = oneshot:: channel ( ) ;
490
- let notify = OneshotNotify :: Async ( sender) ;
491
- self . base
492
- . send_control_msg ( ControlMessage :: Resume { notify } ) ;
486
+ // Ask the audio host to resume the stream
487
+ backend_manager_guard. resume ( ) ;
493
488
494
- // Drop the Mutex guard so we won't hold it across an await
495
- drop ( backend_manager_guard) ;
489
+ // Then, ask to resume rendering via a control message
490
+ log:: debug!( "Resumed audio stream, waking audio graph" ) ;
491
+ let notify = OneshotNotify :: Async ( sender) ;
492
+ self . base
493
+ . send_control_msg ( ControlMessage :: Resume { notify } ) ;
494
+
495
+ // Drop the Mutex guard so we won't hold it across an await point
496
+ }
496
497
497
498
// Wait for the render thread to have processed the resume message
498
499
// The AudioContextState will be updated by the render thread.
@@ -767,4 +768,19 @@ mod tests {
767
768
let time5 = context. current_time ( ) ;
768
769
assert_eq ! ( time5, time4) ; // no progression of time
769
770
}
771
+
772
+ fn require_send_sync < T : Send + Sync > ( _: T ) { }
773
+
774
+ #[ test]
775
+ fn test_all_futures_thread_safe ( ) {
776
+ let options = AudioContextOptions {
777
+ sink_id : "none" . into ( ) ,
778
+ ..AudioContextOptions :: default ( )
779
+ } ;
780
+ let context = AudioContext :: new ( options) ;
781
+
782
+ require_send_sync ( context. suspend ( ) ) ;
783
+ require_send_sync ( context. resume ( ) ) ;
784
+ require_send_sync ( context. close ( ) ) ;
785
+ }
770
786
}
0 commit comments