13个不稳定版本 (3个重大更改)
0.3.1 | 2023年10月26日 |
---|---|
0.3.0 | 2023年10月20日 |
0.2.5 | 2023年10月18日 |
0.2.3 | 2023年8月9日 |
0.0.1 | 2023年7月29日 |
#136 在 异步 中
每月下载量4,103次
在 4 个crate中(3个直接使用) 使用
46KB
574 行
🗑 async-dropper
async-dropper
可能是你见过的最差的Ad-hoc AsyncDrop
实现,并且它以两种方式工作
async_dropper::AsyncDropper
几乎是从 这个StackOverflow回答 中直接复制(感谢paholg
!)async_dropper::AsyncDrop
是一个Trait和 自定义derive宏,它尝试使用Default
和PartialEq
来确定何时异步丢弃,在Drop
时自动进行。
此crate中的代码最直接受到 这个StackOverflow关于Async Drop的线程 和许多其他对话的启发
- 异步丢弃? - Reddit
- 异步析构函数 - rust-lang.org
- 异步丢弃路线图(一旦完成,此crate将被弃用!)
安装
您必须为此crate设置功能,因为它与两种异步运行时都兼容,并可以使用上面概述的 任一 方法
# if using tokio, choose one of the two lines below
cargo add async-dropper --features tokio,derive # use tokio, with the derive approach
cargo add async-dropper --features tokio,simple # use tokio, with the simple approach
# if using async-std, chose one of the two lines below
cargo add async-dropper --features async-std,derive # use async-std, with the derive approach
cargo add async-dropper --features async-std,simple # use async-std, with the simple approach
如果您手动编辑 Cargo.toml
,请 选择以下行之一
[dependencies]
#async-dropper = { version = "0.3", features = [ "tokio", "derive" ] }
#async-dropper = { version = "0.3", features = [ "tokio", "simple" ] }
#async-dropper = { version = "0.3", features = [ "async-std", "derive" ] }
#async-dropper = { version = "0.3", features = [ "async-std", "simple" ] }
警告
async-dropper
不允许同时使用async-std
和tokio
功能(请参阅下面的 常见问题解答)。但是,您可以使用simple
和derive
功能同时使用
快速入门
async_dropper::simple
要使用使用包装结构体(AsyncDropper<<T>>
)的“简单”版本,请参阅examples/simple_tokio.rs
use std::{
result::Result,
time::Duration,
};
use async_dropper_simple::{AsyncDrop, AsyncDropper};
use async_trait::async_trait;
// NOTE: this example is rooted in crates/async-dropper
/// This object will be async-dropped (which must be wrapped in AsyncDropper)
#[derive(Default)]
struct AsyncThing(String);
#[async_trait]
impl AsyncDrop for AsyncThing {
async fn async_drop(&mut self) {
eprintln!("async dropping [{}]!", self.0);
tokio::time::sleep(Duration::from_secs(2)).await;
eprintln!("dropped [{}]!", self.0);
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
{
let _example_obj = AsyncDropper::new(AsyncThing(String::from("test")));
eprintln!("here comes the (async) drop");
// drop will be triggered here, and it will take *however long it takes*
// you could also call `drop(_example_obj)`
}
Ok(())
}
您可以运行示例并查看输出
cargo run --example simple-tokio --features=tokio
async_dropper::派生
派生宏是一个尝试实现AsyncDrop
(但不实际包装现有结构体)的创新(可能也是鲁莽)的尝试。
async_dropper::derive
使用Default
和PartialEq
来检查问题结构体是否与其默认值等效。
为了使这种方法有效,您的T
应该具有低成本创建的Default
,并且将默认值与现有值进行比较应该有意义的差异(并识别不再使用的对象)。请仔细考虑此模型是否适用于您的用例。
例如,请参阅examples/derive_tokio.rs
use std::{
result::Result,
time::Duration,
};
use async_dropper::derive::AsyncDrop;
use async_trait::async_trait;
/// This object will be async-dropped
///
/// Objects that are dropped *must* implement [Default] and [PartialEq]
/// (so make members optional, hide them behind Rc/Arc as necessary)
#[derive(Debug, Default, PartialEq, Eq, AsyncDrop)]
struct AsyncThing(String);
/// Implementation of [AsyncDrop] that specifies the actual behavior
#[async_trait]
impl AsyncDrop for AsyncThing {
// simulated work during async_drop
async fn async_drop(&mut self) -> Result<(), AsyncDropError> {
eprintln!("async dropping [{}]!", self.0);
tokio::time::sleep(Duration::from_secs(2)).await;
eprintln!("dropped [{}]!", self.0);
Ok(())
}
fn drop_timeout(&self) -> Duration {
Duration::from_secs(5) // extended from default 3 seconds, as an example
}
// NOTE: the method below is automatically derived for you, but you can override it
// make sure that the object is equal to T::default() by the end, otherwise it will panic!
// fn reset(&mut self) {
// self.0 = String::default();
// }
// NOTE: below was not implemented since we want the default of DropFailAction::Continue
// fn drop_fail_action(&self) -> DropFailAction;
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
{
let _example_obj = AsyncThing(String::from("test"));
eprintln!("here comes the (async) drop");
// drop will be triggered here
// you could also call `drop(_example_obj)`
}
Ok(())
}
您可以运行示例并查看输出
cargo run --example derive-tokio --features=tokio
支持的环境
async-dropper
与以下异步环境兼容
名称 | 是否支持? |
---|---|
与tokio 的异步 |
✅ |
与async-std 的异步 |
✅ |
常见问题解答(FAQ)
为什么async-dropper
假设我正在使用either async-std
或tokio
?
因为您很可能正在使用。如果这对您来说是个问题,它可以更改,请提交问题。
为什么我必须在simple
和derive
功能之间选择?
simple
策略和derive
策略对它们所作用的T
有不同的要求。
为了避免要求不必要的和可能不兼容的特性,您应该选择一个功能(即方法)来使用。
如果这个“功能”给您带来问题,它可以更改,请提交问题。
async_dropper::derive
的成本是什么?
async_dropper::derive
引入了浪费,即
- 一个受
Mutex
保护的T::default()
实例,该实例在程序运行期间存在 - 一个额外的
T::default()
,它由一个被丢弃的T
组成。
因此,您对T执行的每次drop
都会执行两次丢弃——一次是对T::default()
的丢弃,另一次是对您的 T
的丢弃,该T
已被转换为 T::default
(通过reset(&mut self)
)。
开发
要开始开发 async-dropper
,请运行以下 just
目标
just setup build
为了检查您的更改是否正确,您可能需要运行
just test
如果您想查看可以运行而不带任何参数的完整目标列表。
just
有一些有用的目标,如 just build-watch
,它将不断构建项目,归功于 cargo watch
。
发布
从该存储库的顶级目录
PUBLISH_CRATE=yes PKG=<crate name> just release <version>
例如,要为 patch
创建下一个 async-dropper-simple
的版本
PUBLISH_CRATE=yes PKG=async-dropper-simple just release patch
贡献
欢迎贡献!如果您发现 async-dropper
中应包含的错误或改进,请 [创建问题][crate-issue] 或发起拉取请求。
依赖项
~1–12MB
~137K SLoC