NAME
Future::Uring - Future-returning io_uring functions
VERSION
version 0.001
SYNOPSIS
use Future::Uring;
use Future::AsyncAwait;
my $handle = await Future::Uring::open("input.txt");
my $result = await $handle->write($buffer);
DESCRIPTION
NOTE: This module is an early/experimental release, API stability is not guaranteed yet.
This module is an end-user friendly wrapper around Linux' io_uring mechanism. Uring is based on two sets of ring buffers, the submission queue and the completion queue. For every I/O request you need to make (like to read a file, write a file, accept a socket connection, etc), you create a submission queue entry, that describes the I/O operation you need to get done and add it to the tail of the submission queue (SQ). Most functions have the same name name as their synchronous counterparts.
All IO functions take the following optional named parameters (many take additional ones):
async
Normal operation for io_uring is to try and issue a submission as non-blocking first, and if that fails, execute it in an async manner. To support more efficient overlapped operation of requests that the application knows/assumes will always (or most of the time) block, the application can ask for a submission to be issued async from the start. Note that this flag immediately causes the submission event to be offloaded to an async helper thread with no initial non-blocking attempt. This may be less efficient and should not be used liberally or without understanding the performance and efficiency tradeoffs.
link
When this flag is specified, the submission event forms a link with the next submission event in the submission ring. That next submission event will not be started before the previous request completes. This, in effect, forms a chain of submission events, which can be arbitrarily long. The tail of the chain is denoted by the first submission event that does not have this flag set. Chains are not supported across submission boundaries. Even if the last submission event in a submission has this flag set, it will still terminate the current chain. This flag has no effect on previous submission event submissions, nor does it impact submission events that are outside of the chain tail. This means that multiple chains can be executing in parallel, or chains and individual submission events. Only members inside the chain are serialized. A chain of submission events will be broken if any request in that chain ends in error.
hardlink
Like
link, except the links aren't severed if an error or unexpected result occurs.drain
When this flag is specified, the submission event will not be started before previously submitted submission events have completed, and new submission events will not be started before this one completes.
timeout
This adds a link timeout to the request
timeout_clock
This sets the timeout clock. It defaults to
monotonic.timeout_absolute
If set, the passed timeout will not be a relative time
Several functions have two versions, the second one ending in at (e.g. open and openat). In such cases the latter takes an additional directory descriptor as argument for each path argument; this will be used as base instead of the current directory. Passing undef is equivalent to passing it the current directory.
FUNCTIONS
run_once
Future::Uring::run_once($timeout = undef)
This will submit all pending submission events. It will wait for $timeout seconds for events, or indefinitely if it's undefined.
submit
Future::Uring::submit;
This will submit all pending submissions to the kernel.
submissions_available
Future::Uring::submissions_available;
Check the number of available submission queue events. One may need to submit pending entries before creating a chain, because all entries in a linked chains must be submitted together.
to_handle
my $handle = Future::Uring::to_handle($fh)
This takes a Perl handle and turns it into a Future::Uring::Handle.
link / linkat
await Future::Uring::link($old_path, $new_path, %options)
await Future::Uring::linkat($old_dirh, $old_path, $new_dir, $new_path, %options)
This creates a hard link from $new_path to $old_path.
This takes one additional named argument: follow_symlink, if true and $oldpath is a symlink, it will be followed before the operation.
mkdir / mkdirat
await Future::Uring::mkdir($dirname, %options)
await Future::Uring::mkdirat($dirh, $dirname, %options)
Make directory $dirname.
open / openat
my $handle = await Future::Uring::open($filename, $mode = '<', %options);
my $handle = await Future::Uring::openat($dirh, $filename, $mode = '<', %options);
This opens a file, and returns it as a new handle.
This takes several additional options:
mode
The permission mode that will be used if the file is newly created (e.g.
0644).d_sync
If true, write operations on the file will complete according to the requirements of synchronized I/O data integrity completion.
exclusive
Ensure that this call creates the file: if this flag is specified in conjunction with a creating
$mode, and path already exists, then open() fails with the errorEEXIST.no_follow
If the trailing component (i.e., basename) of path is a symbolic link, then the open fails with the error ELOOP. Symbolic links in earlier components of the pathname will still be followed.
sync
If true write operations on the file will complete according to the requirements of synchronized I/O file integrity completion (by contrast with the synchronized I/O data integrity completion provided by
d_sync.tempfile
Create an unnamed temporary regular file. The path argument specifies a directory; an unnamed inode will be created in that directory's filesystem. Anything written to the resulting file will be lost when the last file descriptor is closed, unless the file is given a name.
rename / renameat
await Future::Uring::rename($old_path, $new_path, %options)
await Future::Uring::renameat($old_dirh, $old_path, $new_dirh, $new_path, %options)
Rename the file at $old_path to $new_path.
exchange
Atomically exchange oldpath and newpath. Both pathnames must exist but may be of different types (e.g., one could be a non-empty directory and the other a symbolic link).
no_replace
Don't overwrite newpath of the rename. Return an error if newpath already exists.
rmdir / rmdirat
await Future::Uring::rmdir($dir, %options)
await Future::Uring::rmdirat($dirh, $dir, %options)
socket
my $handle = await Future::Uring::socket($socket, $domain, $type = STREAM_SOCKET, $protocol = 0);
This creates a new handle, taking the same arguments as perl's built-in socket.
timeout_for
await Future::Uring::timeout_for($seconds, %options)
This creates a relative timeout for $seconds. $seconds must either be a number or a Time::Spec object.
It takes one additional named argument: clock, with allowed values are 'monotonic' (default), 'boottime' and 'realtime'.
timeout_until
await Future::Uring::timeout_until($moment, %options)
This creates an absolute timeout for $moment. $moment must either be a number or a Time::Spec object.
It takes one additional named argument: clock, with allowed values are 'monotonic', 'boottime' and 'realtime' (default).
unlink / unlinkat
await Future::Uring::unlink($filename, %options)
await Future::Uring::unlinkat($dirh, $filename, %options)
This will unlink the file at $filename.
waitid
await Future::Uring::waitid($type, $id, %options)
This will wait for a child process to terminate. It will return the status as a Signal::Info object. The mechanism of process selection depends on the value of $type.
'pid'It will wait for the process whose pid if
$id'pgid'It will wait for a child process from process group
$id.'pidfd'This will wait for the process behind pidfd
$id, which may be a Linux::FD::Pid object instead of a descriptor.'all'This will ignore the value of
$id, and will wait for any child.
It takes the following additional named arguments:
eventThe type of event what is waited for, it can be any of
'exited'(the default),'stopped'or'continued'.nowaitIf true, it will leave the child in a waitable state.
waitpid
await Future::Uring::waitpid($pid, %options)
This is a wrapper of waitid('pid', $pid, %options), except that it will return a conventional exit status instead of a Signal::Info object.
AUTHOR
Leon Timmermans <fawaka@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2025 by Leon Timmermans.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.