4 个版本
0.2.0 | 2022 年 4 月 20 日 |
---|---|
0.1.2 | 2022 年 4 月 14 日 |
0.1.1 | 2022 年 4 月 14 日 |
0.1.0 | 2022 年 4 月 14 日 |
2475 在 Rust 模式 中
13KB
108 行
Rust 特质 + 智能指针,用于手动对象销毁
此软件包引入了用于手动对象销毁的 Close
特质。虽然与 Drop
的目的相似,但主要区别在于 close
方法会获取 self
的所有权,并允许错误传播。为了与 Drop
一起使用,此软件包还引入了 Closing<T: Close>
智能指针,这是一个零成本抽象,如果对象未被手动关闭,则在其释放时关闭包含的对象。
动机
在需要销毁序列执行释放或移动成员的情况下,拥有 self
的所有权很有用。使用 drop
,这需要像以下示例中那样将成员放在一个 Option
中,在该示例中,在继续拆解过程之前连接一个线程(移动其句柄)。这种结构的缺点是增加了运行时成本,并降低了通过选项访问数据后的可用性。
struct DeepThought(Option<std::thread::JoinHandle<u32>>);
impl DeepThought {
fn new() -> Self {
Self(Some(std::thread::spawn(|| 42)))
}
fn thread(&self) -> &std::thread::Thread {
self.0.as_ref().unwrap().thread() // <-- not great
}
}
impl Drop for DeepThought {
fn drop(&mut self) {
match self.0.take().unwrap().join() {
Err(e) => std::panic::resume_unwind(e),
Ok(_answer) => /*... teardown ...*/ ()
}
}
}
使用 close
而不是 drop
,我们可以避免选项舞蹈,并像自然那样编写东西
use close::{Close, Closing};
struct DeepThought(std::thread::JoinHandle<u32>);
impl DeepThought {
fn new() -> Closing<Self> {
Self(std::thread::spawn(|| 42)).into()
}
fn thread(&self) -> &std::thread::Thread {
self.0.thread() // <-- better!
}
}
impl Close for DeepThought {
type Error = String;
fn close(self) -> Result<(), Self::Error> {
match self.0.join() {
Err(e) => Err(format!("thread panicked: {:?}", e)),
Ok(_answer) => /*... teardown ...*/ Ok(()),
}
}
}
请注意,除了避免 Option
之外,构造函数现在返回 Closing
智能指针。因此,第二个实现可以像前者一样精确地使用,使用自动解引用来访问成员和方法,并在对象超出作用域时连接线程。区别在于后者允许更易于使用的实现,不产生任何运行时成本,并在需要错误处理的情况下允许手动关闭。