Open bonsairobo opened 3 months ago
Hi, thanks for opening an issue.
Could you give a code example? I do not quite get the point.
@al8n Sure!
Because lock_shared
and lock_exclusive
may cause the OS to sleep the thread, this would negatively impact performance in a thread-per-core async runtime. So the FileExt
trait is not well-suited for async usage, which seems to conflict with the fact that it is implemented for async_fs::File
.
In order to avoid this, I would use the blocking
crate, which provides a thread pool specifically for blocking IO like this.
let f = Arc::new(async_fs::File::open("lockfile"));
let f2 = f.clone();
unblock(move || f2.lock_shared()).await?;
// Now `f` refers to a locked file handle.
As you can see, unblock
requires a 'static
closure, so we must move
the file handle into the closure.
The unfortunate thing about this is that it's necessary to wrap the file in Arc
. If you look at the definition of async_fs::File
, it actually already has an Arc<std::fs::File>
. I'm not sure if there is some way we can leverage this implementation detail, or perhaps instead it would be possible to provide a new AsyncFileExt
which avoids the Arc
by cloning raw file descriptors. I'm not advocating for any particular solution, but it seems there are possibilities.
Ah, I got it. Yes, I will work on this in the near future.
Hi, sorry for the delay; after I review the code, you can use try_lock_exclusive
or try_lock_shared
to acquire a non-blocking file lock.
@al8n try_lock
is not quite what I want because it will just return immediately on failure instead of yielding the task/future.
@al8n
try_lock
is not quite what I want because it will just return immediately on failure instead of yielding the task/future.
From my point of view, it is hard to make it a "real async task" for locking. We cannot avoid the system call. Even async_fs::File
's implementation, for open,
write,
read
, and etc., just use the unblock
method to spawn a new task and wait for the task to finish.
Actually, unlike network I/O, you can have great performance improvement using async stuff. For file I/O, there is almost no benefit to using async implementation. This is why databases like redb
, sled
, and etc use sync File, which may provide some async APIs on the high level.
Right now, there are blocking methods of
AsyncFileExt
likelock_shared
andlock_exclusive
that could be async for implementations likeasync_fs
ortokio
.I can't see a simple way to do this as a user without wrapping
async_fs::File
in yet anotherArc
to pass it intoblocking::unblock
.