#builder-pattern #exception #unwind #safety #unsafe #finally

unwind_safe

通过类似于try-finally的构建器模式实现可读的unwind-safe代码

3个不稳定版本

0.1.0 2021年12月31日
0.0.1 2021年3月5日

1438Rust模式 中排名

Download history 15843/week @ 2024-03-14 14599/week @ 2024-03-21 10331/week @ 2024-03-28 15297/week @ 2024-04-04 14141/week @ 2024-04-11 16936/week @ 2024-04-18 16312/week @ 2024-04-25 14521/week @ 2024-05-02 15798/week @ 2024-05-09 18616/week @ 2024-05-16 20651/week @ 2024-05-23 21565/week @ 2024-05-30 16040/week @ 2024-06-06 14743/week @ 2024-06-13 19341/week @ 2024-06-20 16857/week @ 2024-06-27

71,155 每月下载量
32 个crate中使用 (直接使用3个)

Zlib OR MIT OR Apache-2.0

10KB
118

::unwind_safe

Repository Latest version Documentation MSRV License CI

通过类似于try-finally的构建器模式实现可读的unwind-safe代码

let mut body_called = false;
let mut finally_called = false;

// Let's imagine some code being run in a context where
// panics do not affect us (`panic::catch_unwind`), or some
// executor running stuff on another thread…
let _ = ::crossbeam::thread::scope(|s| drop(s.spawn(|_| {

    let ft = {
        ::unwind_safe::with_state(())
            .try_eval(|_| {
                body_called = true;
                if ::rand::random() {
                    panic!();
                } else {
                    42
                }
            })
            .finally(|_| { // <- The point of this crate!
                finally_called = true;
            })
    };
    // This is only reached when `try_eval` does not panic, obviously.
    assert_eq!(ft, 42);

})));

// Whatever code path was taken, the finally block is always executed
// (that's the point of this crate!).
// From a place that survives the panic (if any), we thus observe:
assert!(body_called);
assert!(finally_called);

具有实际拥有的状态

如果析构函数需要访问 finally / 延迟块中的拥有的 State1 (type State =: 您选择的类型),

  1. 您可以将它传递给 ::unwind_safe::with_state::<State> API入口点;

  2. 然后 .try_eval(|state: &mut State| {}) 块将能够通过闭包的参数访问到它的一个 独占 借用(&mut),

  3. .finally 块将能够通过其自己的闭包参数以拥有的方式访问该状态:.finally(|state: State| {})

1 这种“拥有”状态仍然可能是一个借用,例如,type State = &mut;

unsafe代码能否依赖finally代码总是被执行?

是的!这正是crate的目的,也是为什么它会这样命名:你可以使用这个.finally模式来确保你的unsafe代码是可恢复的 ✅

类似于::scopeguard

这类似于::scopeguard::defer!,但是增加了在finally / defer块中获得所有权的访问能力,同时仍然让主块拥有对它的&mut引用。

因此,实际上它与::scopeguard::guard相同!这两个之间唯一的(但至关重要的)区别是代码的可读性:在.try_eval().finally()中,可以更明显地看出.finally()部分的代码是在主块代码之后运行的,而在::scopeguard的API中并不是那么明显(需要知道它是如何工作的)。

没有运行时依赖