Break reference cycle in voice storage example (#44)
Changes a stored `Arc` pointer to the call (used to queue up further tracks in response to events) into a `Weak`, as the event handler's strong pointer would keep the Call and Driver objects alive. This would have caused an unintentional resource leak of threads/tasks. This was found by some internal profiling in search of #42.
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
//! git = "https://github.com/serenity-rs/serenity.git"
|
//! git = "https://github.com/serenity-rs/serenity.git"
|
||||||
//! features = ["cache", "framework", "standard_framework", "voice"]
|
//! features = ["cache", "framework", "standard_framework", "voice"]
|
||||||
//! ```
|
//! ```
|
||||||
use std::{collections::HashMap, convert::TryInto, env, sync::Arc};
|
use std::{collections::HashMap, convert::TryInto, env, sync::{Arc, Weak}};
|
||||||
|
|
||||||
use serenity::{
|
use serenity::{
|
||||||
async_trait,
|
async_trait,
|
||||||
@@ -206,7 +206,7 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
|
|||||||
|
|
||||||
let (handler_lock, success_reader) = manager.join(guild_id, connect_to).await;
|
let (handler_lock, success_reader) = manager.join(guild_id, connect_to).await;
|
||||||
|
|
||||||
let call_lock_for_evt = handler_lock.clone();
|
let call_lock_for_evt = Arc::downgrade(&handler_lock);
|
||||||
|
|
||||||
if let Ok(_reader) = success_reader {
|
if let Ok(_reader) = success_reader {
|
||||||
let mut handler = handler_lock.lock().await;
|
let mut handler = handler_lock.lock().await;
|
||||||
@@ -237,21 +237,23 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct LoopPlaySound {
|
struct LoopPlaySound {
|
||||||
call_lock: Arc<Mutex<Call>>,
|
call_lock: Weak<Mutex<Call>>,
|
||||||
sources: Arc<Mutex<HashMap<String, CachedSound>>>,
|
sources: Arc<Mutex<HashMap<String, CachedSound>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl VoiceEventHandler for LoopPlaySound {
|
impl VoiceEventHandler for LoopPlaySound {
|
||||||
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
|
async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> {
|
||||||
|
if let Some(call_lock) = self.call_lock.upgrade() {
|
||||||
let src = {
|
let src = {
|
||||||
let sources = self.sources.lock().await;
|
let sources = self.sources.lock().await;
|
||||||
sources.get("loop").expect("Handle placed into cache at startup.").into()
|
sources.get("loop").expect("Handle placed into cache at startup.").into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut handler = self.call_lock.lock().await;
|
let mut handler = call_lock.lock().await;
|
||||||
let sound = handler.play_source(src);
|
let sound = handler.play_source(src);
|
||||||
let _ = sound.set_volume(0.5);
|
let _ = sound.set_volume(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user