- Notifications
You must be signed in to change notification settings - Fork6
🗑 async-dropper is probably the least-worst ad-hoc AysncDrop implementation you've seen so far.
License
t3hmrman/async-dropper
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
async-dropper
is probably the least-worst ad-hocAsyncDrop
implementation you've seen, and it works in two ways:
async_dropper::AsyncDropper
is stolen nearly verbatim fromthis StackOverflow answer (thanks topaholg
!)async_dropper::AsyncDrop
is a Trait andcustom derive macro, which try to useDefault
andPartialEq
to determine when to async drop, automatically whileDrop
ing.
The code in this crate was most directly inspired bythis StackOverflow thread on Async Drop and many other conversations:
- Async Drop? - Reddit
- Asynchronous Destructors - rust-lang.org
- Async Drop roadmap (once this is done, this crate will be deprecated!)
Youmust set features on this crate, as it works with both async runtimes, and can useeither approach outlined above:
#if using tokio, choose one of the two lines belowcargo add async-dropper --features tokio,derive # use tokio, with the derive approachcargo add async-dropper --features tokio,simple # use tokio, with the simple approach#if using async-std, chose one of the two lines belowcargo add async-dropper --features async-std,derive # use async-std, with the derive approachcargo add async-dropper --features async-std,simple # use async-std, with the simple approach
If you're editingCargo.toml
by hand,choose one of the following lines:
[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" ] }
Warning
async-dropper
does not allow using bothasync-std
andtokio
features at the same time (seethe FAQ below).Youcan, however, use both thesimple
andderive
features at the same time
Here are some other features you might be interested in using:
Crate | Feature | Description |
---|---|---|
async-dropper | anyhow | Enableanyhow -related functionality (ex.From instances) |
To use the "simple" version which uses a wrapper struct (AsyncDropper<T>
), seeexamples/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)]structAsyncThing(String);#[async_trait]implAsyncDropforAsyncThing{asyncfnasync_drop(&mutself){eprintln!("async dropping [{}]!",self.0); tokio::time::sleep(Duration::from_secs(2)).await;eprintln!("dropped [{}]!",self.0);}}#[tokio::main]asyncfnmain() ->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(())}
You can run the example and see the output:
cargo run --example simple-tokio --features=tokio
Itwas suggested that for certain large structs, it may not be convenient to implementDefault
in order to use the simpleAsyncDropper
.
As of version0.2.6
,async-dropper-simple
has a feature flag calledno-default-bound
which allows you to skip theDefault
bound on yourT
(inAsyncDropper<T>
), by using an innerOption<T>
(thanks @beckend!).
The derive macro is a novel (and possibly foolhardy) attempt to implementAsyncDrop
without actually wrapping the existing struct.
async_dropper::derive
usesDefault
andPartialEq
tocheck if the struct in question is equivalent to it's default.
For this approach to work well yourT
should have cheap-to-createDefault
s, and comparing a default value to an existing value should meaningfully differ (and identify an object that is no longer in use).Please think thoroughly about whether this model works for your use case.
For an example, seeexamples/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)]structAsyncThing(String);/// Implementation of [AsyncDrop] that specifies the actual behavior#[async_trait]implAsyncDropforAsyncThing{// simulated work during async_dropasyncfnasync_drop(&mutself) ->Result<(),AsyncDropError>{eprintln!("async dropping [{}]!",self.0); tokio::time::sleep(Duration::from_secs(2)).await;eprintln!("dropped [{}]!",self.0);Ok(())}fndrop_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]asyncfnmain() ->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(())}
You can run the example and see the output:
cargo run --example derive-tokio --features=tokio
async-dropper
works with the following async environments:
Name | Supported? |
---|---|
Async w/tokio | ✅ |
Async w/async-std | ✅ |
Because you probably are. If this is a problem for you, itcan be changed, pleasefile an issue.
Thesimple
strategy andderive
strategy impose different requirements on theT
on which they act.
To avoid requiring unnnecessary and possibly incompatible traits, you should chooseone of the features (i.e. approaches) to go with.
If this "feature" presents an issue for you, itcan be changed, pleasefile an issue.
There is waste introduced byasync_dropper::derive
, namely:
- One
Mutex
-protectedT::default()
instance of your type, that exists as long as the program runs - One extra
T::default()
that is made of an individualT
being dropped.
As a result, everydrop
you perform on a T will perform two drops -- one on aT::default()
and another onyourT
, which has beenconverted to aT::default
(viareset(&mut self)
).
To get started working on developingasync-dropper
, run the followingjust
targets:
just setup build
To check that your changes are fine, you'll probably want to run:
just test
If you want to see the full list of targets available that you can runjust
without any arguments.
just
There are a few useful targets likejust build-watch
which will continuously build the project thanks tocargo watch
.
From the top level of this repository:
PUBLISH_CRATE=yes PKG=<crate name> just release <version>
For example, to create the next semverpatch
release forasync-dropper-simple
:
PUBLISH_CRATE=yes PKG=async-dropper-simple just release patch
Contributions are welcome! If you find a bug or an impovement that should be included inasync-dropper
, [create an issue][crate-issue] or open a pull request.
About
🗑 async-dropper is probably the least-worst ad-hoc AysncDrop implementation you've seen so far.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors6
Uh oh!
There was an error while loading.Please reload this page.