/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
usecrate::{in_shutdown, Interrupted, Interruptee}; use rusqlite::{Connection, InterruptHandle}; use std::fmt; use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
/// Interrupt operations that use SQL /// /// Typical usage of this type: /// - Components typically create a wrapper class around an `rusqlite::Connection` /// (`PlacesConnection`, `LoginStore`, etc.) /// - The wrapper stores an `Arc<SqlInterruptHandle>` /// - The wrapper has a method that clones and returns that `Arc`. This allows passing the interrupt /// handle to a different thread in order to interrupt a particular operation. /// - The wrapper calls `begin_interrupt_scope()` at the start of each operation. The code that /// performs the operation periodically calls `err_if_interrupted()`. /// - Finally, the wrapper class implements `AsRef<SqlInterruptHandle>` and calls /// `register_interrupt()`. This causes all operations to be interrupted when we enter /// shutdown mode. pubstruct SqlInterruptHandle {
db_handle: InterruptHandle, // Counter that we increment on each interrupt() call. // We use Ordering::Relaxed to read/write to this variable. This is safe because we're // basically using it as a flag and don't need stronger synchronization guarantees.
interrupt_counter: Arc<AtomicUsize>,
}
/// Begin an interrupt scope that will be interrupted by this handle /// /// Returns Err(Interrupted) if we're in shutdown mode #[inline] pubfn begin_interrupt_scope(&self) -> Result<SqlInterruptScope, Interrupted> { if in_shutdown() {
Err(Interrupted)
} else {
Ok(SqlInterruptScope::new(Arc::clone(&self.interrupt_counter)))
}
}
/// Interrupt all interrupt scopes created by this handle #[inline] pubfn interrupt(&self) { self.interrupt_counter.fetch_add(1, Ordering::Relaxed); self.db_handle.interrupt();
}
}
/// Check if an operation has been interrupted /// /// This is used by the rust code to check if an operation should fail because it was interrupted. /// It handles the case where we get interrupted outside of an SQL query. #[derive(Debug)] pubstruct SqlInterruptScope {
start_value: usize,
interrupt_counter: Arc<AtomicUsize>,
}
// Create an `SqlInterruptScope` that's never interrupted. // // This should only be used for testing purposes. pubfn dummy() -> Self { Self::new(Arc::new(AtomicUsize::new(0)))
}
/// Check if scope has been interrupted #[inline] pubfn was_interrupted(&self) -> bool { self.interrupt_counter.load(Ordering::Relaxed) != self.start_value
}
/// Return Err(Interrupted) if we were interrupted #[inline] pubfn err_if_interrupted(&self) -> Result<(), Interrupted> { ifself.was_interrupted() {
Err(Interrupted)
} else {
Ok(())
}
}
}
// Needed to allow Weak<SqlInterruptHandle> to be passed to `interrupt::register_interrupt` impl AsRef<SqlInterruptHandle> for SqlInterruptHandle { fn as_ref(&self) -> &SqlInterruptHandle { self
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.