RESTinio
|
Class for storing the buffers used for streaming body (request/response). More...
#include <buffers.hpp>
Public Member Functions | |
writable_item_t (const writable_item_t &)=delete | |
writable_item_t & | operator= (const writable_item_t &)=delete |
writable_item_t () | |
writable_item_t (const_buffer_t const_buf) | |
template<typename Datasizeable , typename S = typename std::enable_if_t< !std::is_same< std::vector< writable_item_t >, Datasizeable >::value >> | |
writable_item_t (Datasizeable ds) | |
writable_item_t (const char *str) | |
template<typename Datasizeable > | |
writable_item_t (std::shared_ptr< Datasizeable > sp) | |
writable_item_t (sendfile_t sf_opts) | |
writable_item_t (writable_item_t &&b) | |
writable_item_t & | operator= (writable_item_t &&b) |
~writable_item_t () | |
writable_item_type_t | write_type () const noexcept |
Get a type of a stored buffer object. | |
std::size_t | size () const |
Get the size of the underlying buffer object. | |
asio_ns::const_buffer | buf () const |
Create a buf reference object used by ASIO. | |
sendfile_t & | sendfile_operation () |
Get a reference to a sendfile operation. | |
Private Member Functions | |
void | destroy_stored_buffer () |
Access an item as an object of specific types. | |
Casts a stored object to one of the types. | |
const impl::writable_base_t * | get_writable_base () const noexcept |
Access as writable_base_t item. | |
impl::writable_base_t * | get_writable_base () noexcept |
Access as writable_base_t item. | |
const impl::buf_iface_t * | get_buf () const noexcept |
Access as trivial buf item. | |
impl::buf_iface_t * | get_buf () noexcept |
Access as trivial buf item. | |
impl::sendfile_write_operation_t * | get_sfwo () noexcept |
Access as sendfile_write_operation_t item. | |
Private Attributes | |
writable_item_type_t | m_write_type |
std::array< char, impl::needed_storage_max_size > | m_storage |
A storage for a buffer object of various types. | |
Class for storing the buffers used for streaming body (request/response).
Supporting different types of entities that eventually result in output data sent to peer is a bit tricky. In the first step RESTionio distinguish two types of output data sources:
Also trivial buffers are implemented diferently for different cases, includeing a template classes impl::datasizeable_buf_t<Datasizeable>
and impl::shared_datasizeable_buf_t<Datasizeable>
.
When using RESTinio response builder, response body can be constructed using different types of buffers, and once the result is flushed to the connection it must be sent to the socket. A couple of issues arises here. And one of them is how to store all these heterogeneous buffers with fewer allocations and less boilerplate necessary to handle each corner case. Storing and moving a bunch of buffers as a vector would be nice, but vector demands a single type to be used. And writable_item_t represents a custom variant-like abstraction for storing an arbitrary buffer object (std::variant
itself is not the option as it is restricted to types defined beforehand and cannot benifit from the knowledge that all stored items are types derrived from impl::writable_base_t).
For storing the data of buffers m_storage is used. It is an aligned buffer sufficient to store any impl::writable_base_t descendant (there is a limitation concerned with impl::datasizeable_buf_t). Also writable_item_t exposes interface to treat it like a trivial buffer or a sendfile operation. The type of buffer currently stored in writable_item_t instance a write_type() function used.
Having such writable_item_t class, RESTinio can store a sequence of arbitrary buffers in std::vector
.
As described here (reserve URL) such code contains UB:
The pointer p
obtained at (2) is invalid because the lifetime of buffer
ends at point (1) and address of buffer
can be used as an address of new object T. The solution is to use std::launder function introduced in C++17:
In that case reinterpret_cast<T*>(buffer)
produces an invalid pointer that contain a valid address of new object T. std::launder makes translates that invalid pointer to a valid one and the resulting p
can be used without UB. Because RESTinio is a C++14 library, we use macro RESTINIO_STD_LAUNDER in code. That macro is expanded to actual call of std::launder if C++17 or latter is used.
Definition at line 525 of file buffers.hpp.
|
delete |
|
inline |
Definition at line 531 of file buffers.hpp.
|
inline |
Definition at line 537 of file buffers.hpp.
|
inline |
Definition at line 550 of file buffers.hpp.
|
inline |
Definition at line 560 of file buffers.hpp.
|
inline |
Definition at line 567 of file buffers.hpp.
|
inline |
Definition at line 580 of file buffers.hpp.
|
inline |
Definition at line 586 of file buffers.hpp.
|
inline |
Definition at line 605 of file buffers.hpp.
|
inline |
Create a buf reference object used by ASIO.
Definition at line 624 of file buffers.hpp.
|
inlineprivate |
Definition at line 641 of file buffers.hpp.
|
inlineprivatenoexcept |
Access as trivial buf item.
Definition at line 669 of file buffers.hpp.
|
inlineprivatenoexcept |
Access as trivial buf item.
Definition at line 676 of file buffers.hpp.
|
inlineprivatenoexcept |
Access as sendfile_write_operation_t item.
Definition at line 683 of file buffers.hpp.
|
inlineprivatenoexcept |
Access as writable_base_t item.
Definition at line 655 of file buffers.hpp.
|
inlineprivatenoexcept |
Access as writable_base_t item.
Definition at line 662 of file buffers.hpp.
|
delete |
|
inline |
Definition at line 593 of file buffers.hpp.
|
inline |
Get a reference to a sendfile operation.
Definition at line 634 of file buffers.hpp.
|
inline |
Get the size of the underlying buffer object.
Definition at line 618 of file buffers.hpp.
|
inlinenoexcept |
Get a type of a stored buffer object.
Definition at line 612 of file buffers.hpp.
|
private |
A storage for a buffer object of various types.
Definition at line 698 of file buffers.hpp.
|
private |
Definition at line 647 of file buffers.hpp.