Skip to content
Closed
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
1 change: 1 addition & 0 deletions crates/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ macos-private-api = [
# TODO: Remove in v3 - wry does not have this feature anymore
objc-exception = []
tracing = ["dep:tracing", "wry/tracing"]
tracing-borrows = ["dep:tracing"]
macos-proxy = ["wry/mac-proxy"]
unstable = []
common-controls-v6 = []
Expand Down
76 changes: 62 additions & 14 deletions crates/tauri-runtime-wry/src/windows_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

use crate::WindowWrapper;
use std::{
cell::{BorrowError, BorrowMutError, RefCell},
collections::BTreeMap,
fmt,
sync::{RwLock, TryLockError},
};
use tauri_runtime::window::WindowId;

Expand All @@ -16,17 +16,34 @@ type Result<T, E = Error> = std::result::Result<T, E>;

#[derive(Debug)]
pub enum Error {
Borrow(BorrowError),
BorrowMut(BorrowMutError),
/// The store's lock could not be acquired (already held in a conflicting mode).
Borrow(LockKind),
/// The store's lock was poisoned by a thread panicking while holding it.
Poisoned(LockKind),
WindowNotFound(WindowId),
}

#[derive(Debug, Clone, Copy)]
pub enum LockKind {
Read,
Write,
}

impl fmt::Display for LockKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
LockKind::Read => "read",
LockKind::Write => "write",
})
}
}

impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Borrow(e) => e.fmt(f),
Error::BorrowMut(e) => e.fmt(f),
Error::Borrow(kind) => write!(f, "windows_store {kind} lock unavailable"),
Error::Poisoned(kind) => write!(f, "windows_store {kind} lock poisoned"),
Error::WindowNotFound(id) => write!(f, "Window not in store: {id:?}"),
}
}
Expand All @@ -38,8 +55,32 @@ impl From<Error> for tauri_runtime::Error {
}
}

fn map_try_lock<G>(kind: LockKind, result: std::result::Result<G, TryLockError<G>>) -> Result<G> {
result.map_err(|e| match e {
TryLockError::Poisoned(_) => Error::Poisoned(kind),
TryLockError::WouldBlock => Error::Borrow(kind),
})
}

#[cfg(feature = "tracing-borrows")]
#[track_caller]
fn trace_borrow(kind: LockKind) {
let caller = std::panic::Location::caller();
tracing::trace!(
target: "tauri::runtime::wry::windows_store",
kind = %kind,
line = caller.line(),
column = caller.column(),
thread = format!("{:?}", std::thread::current().id()),
);
}

#[cfg(not(feature = "tracing-borrows"))]
#[inline(always)]
fn trace_borrow(_kind: LockKind) {}

#[derive(Default)]
pub struct WindowsStore(RefCell<BTreeMap<WindowId, WindowWrapper>>);
pub struct WindowsStore(RwLock<WindowMap>);

impl fmt::Debug for WindowsStore {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -48,40 +89,46 @@ impl fmt::Debug for WindowsStore {
}

impl WindowsStore {
#[track_caller]
pub fn window<F, T>(&self, id: WindowId, f: F) -> Result<T>
where
F: FnOnce(&WindowWrapper) -> T,
{
let store = self.0.try_borrow().map_err(Error::Borrow)?;
trace_borrow(LockKind::Read);
let store = map_try_lock(LockKind::Read, self.0.try_read())?;
let window = store.get(&id).ok_or(Error::WindowNotFound(id))?;
Ok(f(window))
}

#[track_caller]
pub fn window_mut<F, T>(&self, id: WindowId, f: F) -> Result<T>
where
F: FnOnce(&mut WindowWrapper) -> T,
{
let mut store = self.0.try_borrow_mut().map_err(Error::BorrowMut)?;
trace_borrow(LockKind::Write);
let mut store = map_try_lock(LockKind::Write, self.0.try_write())?;
let window = store.get_mut(&id).ok_or(Error::WindowNotFound(id))?;
Ok(f(window))
}

#[track_caller]
pub fn store<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&WindowMap) -> T,
{
self.0.try_borrow().map(|s| f(&s)).map_err(Error::Borrow)
trace_borrow(LockKind::Read);
let store = map_try_lock(LockKind::Read, self.0.try_read())?;
Ok(f(&store))
}

#[track_caller]
pub fn store_mut<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&mut WindowMap) -> T,
{
self
.0
.try_borrow_mut()
.map(|mut s| f(&mut s))
.map_err(Error::BorrowMut)
trace_borrow(LockKind::Write);
let mut store = map_try_lock(LockKind::Write, self.0.try_write())?;
Ok(f(&mut store))
}

pub fn insert(&self, id: WindowId, window: WindowWrapper) -> Result<Option<WindowWrapper>> {
Expand All @@ -96,3 +143,4 @@ impl WindowsStore {
})
}
}

2 changes: 1 addition & 1 deletion crates/tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ tauri-macros = { version = "2.6.1", path = "../tauri-macros" }
tauri-utils = { version = "2.9.1", features = [
"resources",
], path = "../tauri-utils" }
tauri-runtime-wry = { version = "2.11.1", path = "../tauri-runtime-wry", default-features = false, optional = true }
tauri-runtime-wry = { version = "2.11.1", path = "../tauri-runtime-wry", default-features = false, optional = true, features = ["tracing-borrows"] }
getrandom = "0.3"
serde_repr = "0.1"
http = "1"
Expand Down
Loading