AFIO  v2.00 late alpha
afio_v2_xxx::io_service Class Reference

An asynchronous i/o multiplexer service. More...

#include "io_service.hpp"

Classes

struct  awaitable_post_to_self
 

Public Types

using extent_type = io_handle::extent_type
 The file extent type used by this i/o service.
 
using size_type = io_handle::size_type
 The memory extent type used by this i/o service.
 
using buffer_type = io_handle::buffer_type
 The scatter buffer type used by this i/o service.
 
using const_buffer_type = io_handle::const_buffer_type
 The gather buffer type used by this i/o service.
 
using buffers_type = io_handle::buffers_type
 The scatter buffers type used by this i/o service.
 
using const_buffers_type = io_handle::const_buffers_type
 The gather buffers type used by this i/o service.
 
template<class T >
using io_request = io_handle::io_request< T >
 The i/o request type used by this i/o service.
 
template<class T >
using io_result = io_handle::io_result< T >
 The i/o result type used by this i/o service.
 

Public Member Functions

void __post_done (post_info *pi)
 
void _post_done (post_info *pi)
 
void _work_enqueued (size_type i=1)
 
void _work_done ()
 
 io_service ()
 
 io_service (io_service &&)=delete
 
 io_service (const io_service &)=delete
 
io_serviceoperator= (io_service &&)=delete
 
io_serviceoperator= (const io_service &)=delete
 
bool using_kqueues () const noexcept
 True if this i/o service is using BSD kqueues.
 
void disable_kqueues ()
 Force disable any use of BSD kqueues.
 
virtual result< bool > run_until (deadline d) noexcept
 
result< bool > run () noexcept
 
template<class U >
void post (U &&f)
 

Static Public Member Functions

static int interruption_signal () noexcept
 
static int set_interruption_signal (int signo=AFIO_IO_POST_SIGNAL)
 

Friends

class async_file_handle
 

Detailed Description

An asynchronous i/o multiplexer service.

This service is used in conjunction with async_file_handle to multiplex initating i/o and completing it onto a single kernel thread. Unlike the io_service in ASIO or the Networking TS, this io_service is much simpler, in particular it is single threaded per instance only i.e. you must run a separate io_service instance one per kernel thread if you wish to run i/o processing across multiple threads. AFIO does not do this for you (and for good reason, unlike socket i/o, it is generally unwise to distribute file i/o across kernel threads due to the much more code executable between user space and physical storage i.e. keeping processing per CPU core hot in cache delivers outsize benefits compared to socket i/o).

Furthermore, you cannot use this i/o service in any way from any thread other than where it was created. You cannot call its run() from any thread other than where it was created. And you cannot initiate i/o on an async_file_handle from any thread other than where its owning i/o service was created.

In other words, keep your i/o service and all associated file handles on their owning thread. The sole function you can call from another thread is post() which lets you execute some callback in the run() of the owning thread. This lets you schedule i/o from other threads if you really must do that.

namespace afio = AFIO_V2_NAMESPACE;
// Create an i/o service for this thread
afio::io_service service;
// Create an async file i/o handle attached to the i/o service for this thread
afio::async_file_handle h = afio::async_file_handle::async_file(service, {}, "temp", afio::file_handle::mode::write, afio::file_handle::creation::if_needed, afio::file_handle::caching::only_metadata, afio::file_handle::flag::unlink_on_first_close).value();
// Truncate to 1Mb
h.truncate(1024 * 4096);
// Launch 8 coroutines, each writing 4Kb of chars 0-8 to every 32Kb block
auto coroutine = [&h](size_t no) -> std::future<void> {
std::vector<afio::byte, afio::utils::page_allocator<afio::byte>> buffer(4096);
memset(buffer.data(), (int) ('0' + no), 4096);
afio::async_file_handle::const_buffer_type bt{buffer.data(), buffer.size()};
for(size_t n = 0; n < 128; n++)
{
// This will initiate the i/o, and suspend the coroutine until completion.
// The caller will thus resume execution with a valid unsignaled future.
auto written = co_await h.co_write({bt, n * 32768 + no * 4096}).value();
written.value();
}
};
std::vector<std::future<void>> coroutines;
for(size_t n = 0; n < 8; n++)
{
// Construct each coroutine, initiating the i/o, then suspending.
coroutines.push_back(coroutine(n));
}
// Pump the i/o, multiplexing the coroutines, until no more work remains.
while(service.run().value())
;
// Make sure nothing went wrong by fetching the futures.
for(auto &i : coroutines)
{
i.get();
}

Constructor & Destructor Documentation

◆ io_service()

afio_v2_xxx::io_service::io_service ( )
inline

Creates an i/o service for the calling thread, installing a global signal handler via set_interruption_signal() if not yet installed if on POSIX and BSD kqueues not in use.

Member Function Documentation

◆ interruption_signal()

static int afio_v2_xxx::io_service::interruption_signal ( )
inlinestaticnoexcept

Returns the signal used for interrupting run_until(). Only used on POSIX when BSD kqueues are not used. Defaults to AFIO_IO_POST_SIGNAL on platforms which use it.

Note
Only present if AFIO_IO_POST_SIGNAL is defined.

◆ post()

template<class U >
void afio_v2_xxx::io_service::post ( U &&  f)
inline

Schedule the callable to be invoked by the thread owning this object and executing run() at its next available opportunity. Unlike any other function in this API layer, this function is thread safe.

288 { _post(detail::make_function_ptr<void(io_service *)>(std::forward<U>(f))); }

◆ run()

result<bool> afio_v2_xxx::io_service::run ( )
inlinenoexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

279 { return run_until(deadline()); }
virtual result< bool > run_until(deadline d) noexcept

◆ run_until()

virtual result<bool> afio_v2_xxx::io_service::run_until ( deadline  d)
inlinevirtualnoexcept

Runs the i/o service for the thread owning this i/o service. Returns true if more work remains and we just handled an i/o or post; false if there is no more work; errc::timed_out if the deadline passed; errc::operation_not_supported if you try to call it from a non-owning thread; errc::invalid_argument if deadline is invalid.

◆ set_interruption_signal()

static int afio_v2_xxx::io_service::set_interruption_signal ( int  signo = AFIO_IO_POST_SIGNAL)
inlinestatic

Sets the signal used for interrupting run_until(), returning the former signal setting. Only used on POSIX when BSD kqueues are not used. Special values are 0 for deinstall global signal handler, and -1 for install to first unused signal between SIGRTMIN and SIGRTMAX. Changing this while any io_service instances exist is a bad idea.

Note
Only present if AFIO_IO_POST_SIGNAL is defined.

The documentation for this class was generated from the following file: