Large STEP imports: no more multi-minute hang, shared STEP text, cancel and progress (#925)
This commit is contained in:
1 parent
dfbf7dd6a8
commit
2f91338d3d
18 files changed
+525
-45
No files matched your search
@@ -0,0 +1,44 @@
|
||||
//! Progress and cooperative cancellation for long kernel work (reading a large STEP file) run
|
||||
//! off the window thread. The caller installs a [`Watch`] around the work with [`watching`];
|
||||
//! the work reports how far it is and stops at its next check once the watch says so. Work
|
||||
//! that nobody watches runs as before.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Someone waiting for long work: told how far it is, and able to stop it.
|
||||
pub trait Watch: Send + Sync {
|
||||
/// Stop at the next check.
|
||||
fn cancelled(&self) -> bool;
|
||||
/// `done` of `total` units of the current step (`stage`, such as "reading" or "converting").
|
||||
fn progress(&self, stage: &'static str, done: usize, total: usize);
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static CURRENT: RefCell<Option<Arc<dyn Watch>>> = const { RefCell::new(None) };
|
||||
}
|
||||
|
||||
/// Run `f` with `watch` seeing the kernel work it does on this thread.
|
||||
pub fn watching<R>(watch: Arc<dyn Watch>, f: impl FnOnce() -> R) -> R {
|
||||
let previous = CURRENT.with(|c| c.replace(Some(watch)));
|
||||
struct Restore(Option<Option<Arc<dyn Watch>>>);
|
||||
impl Drop for Restore {
|
||||
fn drop(&mut self) {
|
||||
if let Some(previous) = self.0.take() {
|
||||
CURRENT.with(|c| *c.borrow_mut() = previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
let _restore = Restore(Some(previous));
|
||||
f()
|
||||
}
|
||||
|
||||
/// The watch over this thread's work, to hand to the worker threads it starts.
|
||||
pub(crate) fn current() -> Option<Arc<dyn Watch>> {
|
||||
CURRENT.with(|c| c.borrow().clone())
|
||||
}
|
||||
|
||||
/// The error long work returns when its watch cancelled it.
|
||||
pub(crate) fn cancelled_error(what: &str) -> crate::KernelError {
|
||||
crate::KernelError::Failed(format!("{what} cancelled"))
|
||||
}
|
||||
Reference in new issue
Block a user