Skip to content

Commit 3c49859

Browse files
committed
impl Drop for async File & Volume with embassy_futures::block_on
1 parent e623266 commit 3c49859

File tree

4 files changed

+45
-9
lines changed

4 files changed

+45
-9
lines changed

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rust-version = "1.76"
1717
bisync = "0.3.0"
1818
byteorder = {version = "1", default-features = false}
1919
defmt = {version = "0.3", optional = true}
20+
embassy-futures = {version = "0.1.1", optional = true}
2021
embedded-hal = "1.0.0"
2122
embedded-hal-async = "1.0.0"
2223
embedded-io = "0.6.1"
@@ -33,6 +34,7 @@ hex-literal = "0.4.1"
3334
sha2 = "0.10"
3435

3536
[features]
36-
default = ["log"]
37+
default = ["log", "async-drop"]
3738
defmt-log = ["dep:defmt"]
3839
log = ["dep:log"]
40+
async-drop = ["dep:embassy-futures"]

src/inner/filesystem/files.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::super::super::{bisync, only_sync};
1+
use super::super::super::{bisync, only_sync, only_async};
22
use super::super::super::{ErrorType, Read, Seek, SeekFrom, Write};
33
use super::super::{
44
filesystem::{ClusterId, DirEntry, Handle},
@@ -49,8 +49,11 @@ impl RawFile {
4949
/// error that may occur will be ignored. To handle potential errors, use
5050
/// the [`File::close`] method.
5151
///
52-
/// For async Files, async drop does not exist in Rust, so you *must* call
53-
/// [`File::close`] when you are done with a File.
52+
/// For async Files, the implementation of [`Drop`] blocks with [`embassy_futures::block_on`]
53+
/// because there is no way to `.await` inside [`Drop::drop`]. If you would prefer
54+
/// to call [`File::close`] manually instead and rely on the async executor you are already
55+
/// using, you can do that by disabling the `async-drop` Cargo feature, which is enabled by
56+
/// default.
5457
pub struct File<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
5558
where
5659
D: BlockDevice,
@@ -150,7 +153,6 @@ where
150153
}
151154
}
152155

153-
// async drop does not yet exist :(
154156
#[only_sync]
155157
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
156158
for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
@@ -163,6 +165,19 @@ where
163165
}
164166
}
165167

168+
#[cfg(feature = "async-drop")]
169+
#[only_async]
170+
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
171+
for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
172+
where
173+
D: BlockDevice,
174+
T: TimeSource,
175+
{
176+
fn drop(&mut self) {
177+
_ = embassy_futures::block_on(self.volume_mgr.close_file(self.raw_file));
178+
}
179+
}
180+
166181
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
167182
core::fmt::Debug for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
168183
where

src/inner/mod.rs

+19-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use core::fmt::Debug;
1919
use embedded_io::ErrorKind;
2020
use filesystem::Handle;
2121

22-
use super::{bisync, only_sync};
22+
use super::{bisync, only_sync, only_async};
2323

2424
#[doc(inline)]
2525
pub use blockdevice::{Block, BlockCache, BlockCount, BlockDevice, BlockIdx};
@@ -210,8 +210,11 @@ impl RawVolume {
210210
/// any error that may occur will be ignored. To handle potential errors, use
211211
/// the [`Volume::close`] method.
212212
///
213-
/// For async Volumes, async drop does not exist in Rust, so you *must* call
214-
/// [`Volume::close`] when you are done with a Volume.
213+
/// For async Volumes, the implementation of [`Drop`] blocks with [`embassy_futures::block_on`]
214+
/// because there is no way to `.await` inside [`Drop::drop`]. If you would prefer
215+
/// to call [`File::close`] manually instead and rely on the async executor you are already
216+
/// using, you can do that by disabling the `async-drop` Cargo feature, which is enabled by
217+
/// default.
215218
pub struct Volume<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
216219
where
217220
D: BlockDevice,
@@ -268,7 +271,6 @@ where
268271
}
269272
}
270273

271-
// async drop does not yet exist :(
272274
#[only_sync]
273275
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
274276
for Volume<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
@@ -281,6 +283,19 @@ where
281283
}
282284
}
283285

286+
#[cfg(feature = "async-drop")]
287+
#[only_async]
288+
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop
289+
for Volume<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
290+
where
291+
D: BlockDevice,
292+
T: TimeSource,
293+
{
294+
fn drop(&mut self) {
295+
_ = embassy_futures::block_on(self.volume_mgr.close_volume(self.raw_volume));
296+
}
297+
}
298+
284299
impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize>
285300
core::fmt::Debug for Volume<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES>
286301
where

src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@
7070
//!
7171
//! ## Features
7272
//!
73+
//! * `async-drop`: Enabled by default. Implements [`Drop`] for [`asynchronous::File`]
74+
//! and [`asynchronous::Volume`] using [`embassy_futures::block_on`]. Disable if
75+
//! you would prefer to call [`asynchronous::File::close`] and [`asynchronous::Volume::close`]
76+
//! manually using the async executor you are already using.
7377
//! * `log`: Enabled by default. Generates log messages using the `log` crate.
7478
//! * `defmt-log`: By turning off the default features and enabling the
7579
//! `defmt-log` feature you can configure this crate to log messages over defmt

0 commit comments

Comments
 (0)