Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::chat::ChatIdBlocked;
use crate::chat::{Chat, ChatId, send_msg};
use crate::constants::{Blocked, Chattype};
use crate::contact::ContactId;
use crate::context::Context;
use crate::context::{Context, WeakContext};
use crate::events::EventType;
use crate::headerdef::HeaderDef;
use crate::log::warn;
Expand Down Expand Up @@ -199,8 +199,9 @@ impl Context {
call.id = send_msg(self, chat_id, &mut call).await?;

let wait = RINGING_SECONDS;
let context = self.get_weak_context();
task::spawn(Context::emit_end_call_if_unaccepted(
self.clone(),
context,
wait.try_into()?,
call.id,
));
Expand Down Expand Up @@ -291,11 +292,12 @@ impl Context {
}

async fn emit_end_call_if_unaccepted(
context: Context,
context: WeakContext,
wait: u64,
call_id: MsgId,
) -> Result<()> {
sleep(Duration::from_secs(wait)).await;
let context = context.upgrade()?;
let Some(mut call) = context.load_call_by_id(call_id).await? else {
warn!(
context,
Expand Down Expand Up @@ -368,8 +370,9 @@ impl Context {
}
}
let wait = call.remaining_ring_seconds();
let context = self.get_weak_context();
task::spawn(Context::emit_end_call_if_unaccepted(
self.clone(),
context,
wait.try_into()?,
call.msg.id,
));
Expand Down
28 changes: 27 additions & 1 deletion src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::ffi::OsString;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, OnceLock};
use std::sync::{Arc, OnceLock, Weak};
use std::time::Duration;

use anyhow::{Context as _, Result, bail, ensure};
Expand Down Expand Up @@ -201,6 +201,25 @@ impl Deref for Context {
}
}

/// A weak reference to a [`Context`]
///
/// Can be used to obtain a [`Context`]. An existing weak reference does not prevent the corresponding [`Context`] from being dropped.
#[derive(Clone, Debug)]
pub(crate) struct WeakContext {
inner: Weak<InnerContext>,
}

impl WeakContext {
/// Returns the [`Context`] if it is still available.
pub(crate) fn upgrade(&self) -> Result<Context> {
let inner = self
.inner
.upgrade()
.ok_or_else(|| anyhow::anyhow!("Inner struct has been dropped"))?;
Ok(Context { inner })
}
}

/// Actual context, expensive to clone.
#[derive(Debug)]
pub struct InnerContext {
Expand Down Expand Up @@ -385,6 +404,13 @@ impl Context {
Ok(context)
}

/// Returns a weak reference to this [`Context`].
pub(crate) fn get_weak_context(&self) -> WeakContext {
WeakContext {
inner: Arc::downgrade(&self.inner),
}
}

/// Opens the database with the given passphrase.
/// NB: Db encryption is deprecated, so `passphrase` should be empty normally. See
/// [`ContextBuilder::with_password()`] for reasoning.
Expand Down
Loading