Previously, previously, and previously.
The Gio.IOStream APIs already provide robust support for asynchronous IO. The common API allows for different types of implementation based on the stream implementation.
Libdex provides wrappers for various APIs. Coverage is not complete but we do expect additional APIs to be covered in future releases.
File Management
See dex_file_copy() for copying files.
See dex_file_delete() for deleting files.
See dex_file_move() for moving files.
File Attributes
See dex_file_query_info() and dex_file_query_file_type(), and dex_file_query_exists() for basic querying.
You can set file attributes using dex_file_set_attributes().
Directories
You can create a directory or hierarchy of directories using dex_file_make_directory() and dex_file_make_directory_with_parents() respectively.
Enumerating Files
You can create a file enumerator for a directory using dex_file_enumerate_children().
You can also asynchronously enumerate the files of that directory using dex_file_enumerator_next_files() which will resolve to a g_autolist(GFileInfo)
of infos.
Reading and Writing Files
The dex_file_read() will provide a Gio.FileInputStream which can be read from.
A simpler interface to get the bytes of a file is provided via dex_file_load_contents_bytes().
The dex_file_replace() will replace a file on disk providing a Gio.FileOutputStream to write to. The dex_file_replace_contents_bytes() provides a simplified API for this when the content is readily available.
Reading Streams
See dex_input_stream_read(), dex_input_stream_read_bytes(), dex_input_stream_skip(), and dex_input_stream_close() for working with input streams asynchronously.
Writing Streams
See dex_output_stream_write(), dex_output_stream_write_bytes(), dex_output_stream_splice(), and dex_output_stream_close() for writing to streams asynchronously.
Sockets
The dex_socket_listener_accept(), dex_socket_client_connect(), and dex_resolver_lookup_by_name() may be helpful when writing socket servers and clients.
D-Bus
Light integration exists for D-Bus to perform asychronous method calls.
See dex_dbus_connection_call(), dex_dbus_connection_call_with_unix_fd_list(), dex_dbus_connection_send_message_with_reply() and dex_dbus_connection_close().
We expect additional support for D-Bus to come at a later time.
Subprocesses
You can await completion of a subprocess using dex_subprocess_wait_check().
Foundry uses some helpers to do UTF-8 communication but I’d like to bring that to libdex in an improved way post-1.0.
Asynchronous IO with File Descriptors
Gio.IOStream and related APIs provides much opertunity for streams to be used asynchronously. There may be cases where you want similar behavior with traditional file-descriptors.
Libdex provides a set of AIO-like functions for traditional file-descriptors which may be backed with more efficient mechanisms.
Gio.IOStream typically uses a thread pool of blocking IO operations on Linux and other operating systems because that was the fastest method when the APIs were created. However, on some operating systems such as Linux, faster methods finally exist.
On Linux, io_uring
can be used for asynchronous IO and is provided in the form of a Dex.Future.
Asynchronous Reads
DexFuture *dex_aio_read (DexAioContext *aio_context, int fd, gpointer buffer, gsize count, goffset offset);
Use the dex_aio_read()
function to read from a file-descriptor. The result will be a future that resolves to a gint64
containing the number of bytes read.
If there was a failure, the future will reject using the appropriate error code.
Your buffer
must stay alive for the duration of the asynchronous read. One easy way to make that happen is to wrap the resulting future in a dex_future_then()
which stores the buffer as user_data
and releases it when finished.
If you are doing buffer pooling, more effort may be required.
Asynchronous Writes
DexFuture *dex_aio_write (DexAioContext *aio_context, int fd, gconstpointer buffer, gsize count, goffset offset);
A similar API exists as dex_aio_read()
but for writing. It too will resolve to a gint64
containing the number of bytes written.
buffer
must be kept alive for the duration of the call and it is the callers responsibility to do so.
You can find this article in the documentation under Asynchronous IO.