Traits
List of types that must be defined be Traits
timer_manager_tdefines the logic of how timeouts are managed;logger_tdefines logger that is used by RESTinio to track its inner logic;request_handler_tdefines a function-like type to be used as request handler;strand_t- defines a class that is used by connection as a wrapper for its callback-handlers running onasio::io_contextthread(s) in order to guarantee serialized callbacks invocation (see asio doc). Actually, there are two options for the strand type:asio::strand<asio::executor>andasio::executor. The first is a real strand that guarantees serialized invocation and the second one is simply a default executor to eliminate unnecessary overhead when runningasio::io_contexton a single thread;stream_socket_tis a customization point that tells restinio what type of socket used for connections. This parameter allows restinio to support TLS connection (see TLS support).
timer_manager_t
timer_manager_t - defines a timeout controller logic.
It must define two nested types.
The first one is timer_guard_t with the following interface:
class timer_guard_t
{
public:
// Schedule a checking of timed out operations
// after the time interval specified by timer-manager.
void schedule(
// Weak pointer to object to check timed out ops.
// tcp_connection_ctx_weak_handle_t = std::weak_ptr< tcp_connection_ctx_base_t >
tcp_connection_ctx_weak_handle_t weak_handle );
// Cancel timeout guard if any.
void cancel();
};
To understand the ground idea behind timer managers it is needed to clarify on
tcp_connection_ctx_base_t a weak pointer of which is passed to
timer_guard_t::schedule(). A class
tcp_connection_ctx_base_t has a virtual method:
// Check timeouts for all activities.
virtual void check_timeout(
// A handle to itself (eliminates one shared_ptr instantiation).
std::shared_ptr< tcp_connection_ctx_base_t > & self ) = 0;
Internal classes that inherit from tcp_connection_ctx_base_t implement this
method to initiate a check whether there are a timed out operations. So
timer_guard_t::schedule() timer guard must simply store a weak pointer to
tcp_connection_ctx_base_t somewhere and try to invoke check_timeout()
after some period of time that is specified by timer manager. Here is an
example of how to try to invoke check_timeout():
// restinio::tcp_connection_ctx_weak_handle_t weak_handle;
if( auto h = weak_handle.lock() )
{
// If here then h is a shared pointer to an exiting object.
h->check_timeout( h );
}
Suppose timer manager sets a time period for checking to 1 second, so each second a context object of a given connection will check if any timeout happened. Between two sequential checks, connection context object may change the actual operation that is tracked for timeout many times.
A timer_guard_t::cancel() method must cancel scheduled check of a given
timer_guard.
An instance of timer_guard_t is stored in each connection
managed by RESTinio and to create it timer_manager_t must define
the following method:
class timer_manager_t
{
public:
// ...
// struct/class timer_guard_t{ ... };
// or
// using timer_guard_t = ...;
// Create guard for connection.
timer_guard_t create_timer_guard();
// ...
};
The second type nested in timer_manager_t must be factory_t,
that must implement create(asio::io_context&) method:
struct factory_t
{
/* Extra parameters for creating timer manager */
auto create( asio::io_context & io_context ) const
{
return std::make_shared< timer_manager_t >( /* params */ );
}
};
Nested factory type is needed for holding parameters of a timer manager that
come from settings. Timer manager itself might need a reference to
asio::io_context on which server runs, and it is not available on the level
of settings object. So the creation of timer instance is done in two steps. The first
step - the factory is created in server settings and stores params that are needed
for creating timer manager. The second step - when the server is instantiated (hence
asio::io_context is known) a timer manager is created using the factory.
RESTinio comes with a set of ready-to-use timer_manager_t implementation:
null_timer_manager_t– noop timer guards, they produce timer guards that do nothing (when no control needed). See restinio/null_timer_manager.hpp;asio_timer_manager_t– timer guards implemented with asio timers. See restinio/asio_timer_manager.hpp;so5::so_timer_manager_t– timer guards implemented with SObjectizer timers. See restinio/so5/so_timer_manager.hpp. Note thatrestinio/so5/so_timer_manager.hppheader file is not included byrestinio/all.hpp, so it needs to be included separately.
logger_t
logger_t - defines a logger implementation.
It must support the following interface:
class null_logger_t
{
public:
template< typename Msg_Builder >
void trace( Msg_Builder && mb );
template< typename Msg_Builder >
void info( Msg_Builder && mb );
template< typename Msg_Builder >
void warn( Msg_Builder && mb );
template< typename Msg_Builder >
void error( Msg_Builder && mb );
};
Msg_Builder is lambda that returns a message to log out.
This approach allows a compiler to optimize logging when it is possible,
see null_logger_t.
For implementation example see ostream_logger_t.
request_handler_t
request_handler_t - is a key type for request handling process.
It must be a function-object with the following invocation interface:
restinio::request_handling_status_t
handler( restinio::request_handle_t req );
See Request handler for more details.
strand_t
strand_t provides serialized callback invocation for events of a specific
connection. There are two option for strand_t: asio::strand<asio::executor> or asio::executor.
By default asio::strand<asio::executor> is used,
it guarantees serialized chain of callback invocation.
But if asio::io_context runs on a single thread there is no need
to use asio::strand because there is no way to run callbacks in parallel.
So in such cases, it is enough to use asio::executor directly and
eliminate the overhead of asio::strand.
stream_socket_t
stream_socket_t allows to customize underlying socket type,
so it possible to create https server using identical interface (see TLS support).