mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Doc work
This commit is contained in:
@ -1,3 +1,9 @@
|
|||||||
|
Version 205
|
||||||
|
|
||||||
|
* Doc work
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 204
|
Version 204
|
||||||
|
|
||||||
* Add basic_timeout_stream
|
* Add basic_timeout_stream
|
||||||
|
@ -18,7 +18,7 @@ A
|
|||||||
allows programs located anywhere to exchange information after opting-in
|
allows programs located anywhere to exchange information after opting-in
|
||||||
to communications by establishing a
|
to communications by establishing a
|
||||||
[@https://en.wikipedia.org/wiki/Data_link ['connection]].
|
[@https://en.wikipedia.org/wiki/Data_link ['connection]].
|
||||||
Data is reliably transferred on a connection in either direction
|
Data may be reliably transferred across a connection in both directions
|
||||||
([@https://en.wikipedia.org/wiki/Duplex_(telecommunications) ['full-duplex]])
|
([@https://en.wikipedia.org/wiki/Duplex_(telecommunications) ['full-duplex]])
|
||||||
with bytes arriving in the same order they were sent. These connections, along
|
with bytes arriving in the same order they were sent. These connections, along
|
||||||
with the objects and types used to represent them, are collectively termed
|
with the objects and types used to represent them, are collectively termed
|
||||||
@ -26,9 +26,9 @@ with the objects and types used to represent them, are collectively termed
|
|||||||
|
|
||||||
The
|
The
|
||||||
[@https://en.wikipedia.org/wiki/Internet ['internet]]
|
[@https://en.wikipedia.org/wiki/Internet ['internet]]
|
||||||
is a global network of interconnected computers which exchange information
|
is a global network of interconnected computers that use a variety of
|
||||||
using a variety of standardized communication protocols. The most popular
|
standardized communication protocols to exchange information. The most
|
||||||
protocol is
|
popular protocol is
|
||||||
[@https://en.wikipedia.org/wiki/Transmission_Control_Protocol ['TCP/IP]],
|
[@https://en.wikipedia.org/wiki/Transmission_Control_Protocol ['TCP/IP]],
|
||||||
which this library relies on exclusively. The protocol takes care of the
|
which this library relies on exclusively. The protocol takes care of the
|
||||||
low level details so that applications see a
|
low level details so that applications see a
|
||||||
@ -67,7 +67,7 @@ objects that perform I/O.
|
|||||||
The networking types __const_buffer__ and __mutable_buffer__ represent
|
The networking types __const_buffer__ and __mutable_buffer__ represent
|
||||||
these memory regions as type-safe pointer/size pairs, as shown below:
|
these memory regions as type-safe pointer/size pairs, as shown below:
|
||||||
```
|
```
|
||||||
net::const_buffer cb("Hello, world!", 13);
|
net::const_buffer cb(string_view("Hello, world!", 13));
|
||||||
assert(string_view(reinterpret_cast<char const*>(cb.data()), cb.size()) == "Hello, world!");
|
assert(string_view(reinterpret_cast<char const*>(cb.data()), cb.size()) == "Hello, world!");
|
||||||
|
|
||||||
char storage[13];
|
char storage[13];
|
||||||
@ -76,26 +76,39 @@ these memory regions as type-safe pointer/size pairs, as shown below:
|
|||||||
assert(string_view(reinterpret_cast<char const*>(mb.data()), mb.size()) == "Hello, world!");
|
assert(string_view(reinterpret_cast<char const*>(mb.data()), mb.size()) == "Hello, world!");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[tip
|
||||||
|
Networking uses custom buffer types because `span<byte>` does too much.
|
||||||
|
It not only type-erases the original pointer but also recasts it to a
|
||||||
|
pointer-to-byte. The operating system doesn't care about this, but if
|
||||||
|
a user wants to send and receive an array of some other type, presenting
|
||||||
|
it as an array of bytes which supports bitwise operations is unnecessary.
|
||||||
|
Custom buffer types also permit networking implmentations to provide
|
||||||
|
targeted features such as
|
||||||
|
[@boost:/doc/html/boost_asio/overview/core/buffers.html#boost_asio.overview.core.buffers.buffer_debugging ['buffer debugging]]
|
||||||
|
without changing the more general vocabulary types.
|
||||||
|
]
|
||||||
|
|
||||||
The concepts
|
The concepts
|
||||||
__ConstBufferSequence__ and __MutableBufferSequence__ describe bidirectional
|
__ConstBufferSequence__ and __MutableBufferSequence__ describe bidirectional
|
||||||
ranges whose value type is convertible to __const_buffer__ and
|
ranges whose value type is convertible to `const_buffer` and
|
||||||
__mutable_buffer__ respectively. Buffer sequences may be used to transact
|
`mutable_buffer` respectively. Buffer sequences may be used to transact
|
||||||
in multiple buffers in a single function call, a technique sometimes
|
in multiple buffers in a single function call, a technique sometimes
|
||||||
referred to as
|
referred to as
|
||||||
[@https://en.wikipedia.org/wiki/Vectored_I/O ['scatter/gather I/O]].
|
[@https://en.wikipedia.org/wiki/Vectored_I/O ['scatter/gather I/O]].
|
||||||
Buffer and buffer sequence types are non-owning; creating a copy only results
|
Buffers and sequences are non-owning; copies produce shallow references and
|
||||||
in a shallow reference and not a duplicate of the underlying memory. These
|
not duplicates of the underlying memory. Each of these statements declares
|
||||||
are all examples of buffer sequences:
|
a buffer sequence:
|
||||||
```
|
```
|
||||||
net::const_buffer b1;
|
net::const_buffer b1;
|
||||||
net::mutable_buffer b2;
|
net::mutable_buffer b2;
|
||||||
std::array<net::const_buffer, 3> b3;
|
std::array<net::const_buffer, 3> b3;
|
||||||
```
|
```
|
||||||
|
|
||||||
The __DynamicBuffer__ concept defines a buffer container which may be
|
The __DynamicBuffer__ concept defines a buffer container with an interface
|
||||||
resized using a well defined interface. Beast and networking use dynamic
|
that supports increasing and decreasing the size of the managed buffer
|
||||||
buffers when the amount of storage required to perform an operation is
|
sequence. Beast and networking use dynamic buffers when the amount of
|
||||||
not known ahead of time, such as when reading a complete HTTP message.
|
storage required to perform an operation is not known ahead of time,
|
||||||
|
such as when reading a complete HTTP message.
|
||||||
|
|
||||||
[heading Synchronous I/O]
|
[heading Synchronous I/O]
|
||||||
|
|
||||||
@ -104,51 +117,50 @@ calls that provide the complete results of the operation upon returning.
|
|||||||
Such operations typically cannot be canceled and do not have a method for
|
Such operations typically cannot be canceled and do not have a method for
|
||||||
setting a timeout. The __SyncReadStream__ and __SyncWriteStream__ concepts
|
setting a timeout. The __SyncReadStream__ and __SyncWriteStream__ concepts
|
||||||
define requirements for
|
define requirements for
|
||||||
['synchronous streams],
|
['synchronous streams]:
|
||||||
permitting portable exchange of data using buffer sequence abstractions
|
a portable I/O abstraction that exchanges data using buffer sequences
|
||||||
to represent bytes and either `error_code` or exceptions to describe any
|
to represent bytes and either `error_code` or an exception to report
|
||||||
failures.
|
any failures.
|
||||||
|
|
||||||
A
|
A
|
||||||
['synchronous stream algorithm]
|
['synchronous stream algorithm]
|
||||||
is written as a function template accepting a stream object meeting the
|
is written as a function template accepting a stream object meeting the
|
||||||
named requirements for synchronous reading, writing, or both. This generic
|
named requirements for synchronous reading, writing, or both. This example
|
||||||
example shows how some text might be written synchronously to a stream,
|
shows an algorithm which writes text and uses exceptions to indicate errors:
|
||||||
using exceptions to indicate errors:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
template <class SyncWriteStream>
|
template <class SyncWriteStream>
|
||||||
void hello (SyncWriteStream& stream)
|
void hello (SyncWriteStream& stream)
|
||||||
{
|
{
|
||||||
net::const_buffer buffer("Hello, world!", 13);
|
net::const_buffer cb(string_view("Hello, world!"));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto bytes_transferred = stream.write_some(buffer); // may throw
|
auto bytes_transferred = stream.write_some(cb); // may throw
|
||||||
buffer += bytes_transferred; // adjust the pointer and size
|
cb += bytes_transferred; // adjust the pointer and size
|
||||||
}
|
}
|
||||||
while (buffer.size() > 0);
|
while (cb.size() > 0);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The same function may be written to use error codes instead of exceptions:
|
The same algorithm may be expressed using error codes instead of exceptions:
|
||||||
|
|
||||||
```
|
```
|
||||||
template <class SyncWriteStream>
|
template <class SyncWriteStream>
|
||||||
void hello (SyncWriteStream& stream, error_code& ec)
|
void hello (SyncWriteStream& stream, error_code& ec)
|
||||||
{
|
{
|
||||||
net::const_buffer buffer("Hello, world!", 13);
|
net::const_buffer cb(string_view("Hello, world!"));
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
auto bytes_transferred = stream.write_some(buffer, ec);
|
auto bytes_transferred = stream.write_some(cb, ec);
|
||||||
buffer += bytes_transferred; // adjust the pointer and size
|
cb += bytes_transferred; // adjust the pointer and size
|
||||||
}
|
}
|
||||||
while (buffer.size() > 0 && ! ec);
|
while (cb.size() > 0 && ! ec);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
[heading Asynchronous I/O]
|
[heading Asynchronous I/O]
|
||||||
|
|
||||||
An asynchronous operation starts with a call to an
|
An asynchronous operation begins with a call to an
|
||||||
[@boost:/doc/html/boost_asio/reference/asynchronous_operations.html ['initiating function]],
|
[@boost:/doc/html/boost_asio/reference/asynchronous_operations.html ['initiating function]],
|
||||||
which starts the operation and returns to the caller immediately. This
|
which starts the operation and returns to the caller immediately. This
|
||||||
['outstanding]
|
['outstanding]
|
||||||
@ -156,98 +168,121 @@ asynchronous operation continues to make progress concurrently without
|
|||||||
blocking. When the externally observable side effects are fully established,
|
blocking. When the externally observable side effects are fully established,
|
||||||
a movable function object known as a
|
a movable function object known as a
|
||||||
[@boost:/doc/html/boost_asio/reference/CompletionHandler.html ['completion handler]]
|
[@boost:/doc/html/boost_asio/reference/CompletionHandler.html ['completion handler]]
|
||||||
provided in the initiating function call is then queued for execution to
|
provided in the initiating function call is queued for execution with the
|
||||||
receive the results of the operation, which may include the error code and other
|
results, which may include the error code and other specific information.
|
||||||
specific information. The operation is considered
|
An asynchronous operation is said to be
|
||||||
['completed]
|
['completed]
|
||||||
when the completion handler has been queued for execution with the results.
|
after the completion handler is queued. The code that follows shows how some
|
||||||
|
text may be written to a
|
||||||
|
[@boost:/doc/html/boost_asio/reference/ip__tcp/socket.html `socket`]
|
||||||
|
asynchronously, invoking a lambda when the
|
||||||
|
operation is complete:
|
||||||
|
```
|
||||||
|
net::async_write(sock, net::const_buffer(string_view("Hello, world!")),
|
||||||
|
[](error_code ec, std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if(! ec)
|
||||||
|
assert(bytes_transferred == 13);
|
||||||
|
else
|
||||||
|
std::cerr << "Error: " << ec.message() << "\n";
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
Every completion handler (also referred to as a
|
Every completion handler (also referred to as a
|
||||||
['continuation]
|
[@https://en.wikipedia.org/wiki/Continuation ['continuation]])
|
||||||
since it represents a continuation of the flow of control that starts
|
has both an
|
||||||
with the initiating function call) has an
|
[@boost:/doc/html/boost_asio/overview/core/allocation.html ['associated allocator]]
|
||||||
[@boost:/doc/html/boost_asio/overview/core/allocation.html ['associated allocator]].
|
and an
|
||||||
Temporary storage obtained using the associated allocator [*must] be deallocated
|
[@boost:/doc/html/boost_asio/reference/associated_executor.html ['associated executor]].
|
||||||
before the completion handler is invoked.
|
The allocator may be used to obtain temporary storage (which [*must] be
|
||||||
Each completion handler also has an
|
deallocated before the completion handler is invoked), while the executor
|
||||||
['associated executor].
|
is a cheaply copyable object providing the algorithm used to invoke the
|
||||||
An executor is a cheaply copyable object that provides an algorithm for
|
completion handler. Unless customized by the caller, a completion handler
|
||||||
invoking nullary function objects.
|
defaults to using `std::allocator<void>` and the executor of the
|
||||||
|
corresponding I/O object.
|
||||||
|
|
||||||
Networking prescribes facilities to determine the context
|
Networking prescribes facilities to determine the context in which
|
||||||
where handlers run. Every I/O object is associated with an
|
handlers run. Every I/O object refers to an __ExecutionContext__ for
|
||||||
__ExecutionContext__,
|
obtaining the __Executor__ instance used to invoke completion handlers.
|
||||||
which permits implementations to store private per-context data and
|
An executor determines where and how completion handlers are invoked.
|
||||||
also supplies instances of its
|
Executors obtained from an instance of __io_context__ offer a basic guarantee:
|
||||||
__Executor__
|
handlers will only be invoked from threads which are currently calling
|
||||||
that determines where and how a handler is invoked in the
|
|
||||||
exection context. Instances of __io_context__ offer a basic guarantee:
|
|
||||||
handlers will only be executed from caller-provided threads which are
|
|
||||||
currently invoking
|
|
||||||
[@boost:/doc/html/boost_asio/reference/io_context/run/overload1.html `net::io_context::run`].
|
[@boost:/doc/html/boost_asio/reference/io_context/run/overload1.html `net::io_context::run`].
|
||||||
|
|
||||||
An
|
|
||||||
[@boost:/doc/html/boost_asio/overview/core/strands.html ['associated executor]]
|
|
||||||
is defined for every completion handler, defaulting to the executor of the
|
|
||||||
target I/O object. The executor for a completion handler may be customized,
|
|
||||||
for example by choosing a __strand__.
|
|
||||||
|
|
||||||
The __AsyncReadStream__ and __AsyncWriteStream__ concepts define requirements for
|
The __AsyncReadStream__ and __AsyncWriteStream__ concepts define requirements for
|
||||||
['asynchronous streams],
|
['asynchronous streams]:
|
||||||
permitting portable exchange of data asynchronously using buffer sequence
|
a portable I/O abstraction that exchanges data asynchronously using buffer
|
||||||
abstractions to represent bytes and `error_code` to describe any failures.
|
sequences to represent bytes and `error_code` to report any failures. An
|
||||||
|
|
||||||
An
|
|
||||||
['asynchronous stream algorithm]
|
['asynchronous stream algorithm]
|
||||||
is written as a templated initiating function template which accepts a stream
|
is written as a templated initiating function template accepting a stream
|
||||||
object meeting the named requirements for asynchronous reading, writing, or
|
object meeting the named requirements for asynchronous reading, writing, or
|
||||||
both. The signature for the initiating function includes a
|
both. This example shows an algorithm which writes some text to an
|
||||||
['completion token],
|
asynchronous stream:
|
||||||
which is a generalization of completion handlers permitting user-defined
|
|
||||||
types such as futures or coroutines to be substituted as the mechanism by
|
|
||||||
which the results of the asynchronous operation are delivered. The following
|
|
||||||
statements all call the same function to asynchronously read data from a
|
|
||||||
stream, but use a different method for receiving the results:
|
|
||||||
```
|
|
||||||
net::async_read(sock, buffer,
|
|
||||||
[error_code ec, std::size_t bytes_transferred]
|
|
||||||
{
|
|
||||||
if(ec)
|
|
||||||
std::cout << "Error: " << ec.message() << "\n";
|
|
||||||
```
|
|
||||||
|
|
||||||
The system
|
|
||||||
for customizing the return type of initiating functions and obtaining the
|
|
||||||
actual completion handler from a completion token is known as the
|
|
||||||
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf ['Universal Model for Asynchronous Operations]] (N3747).
|
|
||||||
|
|
||||||
This generic example shows the signature for an initiating function to write
|
|
||||||
some text to a stream:
|
|
||||||
```
|
```
|
||||||
template <class AsyncWriteStream, class WriteHandler>
|
template <class AsyncWriteStream, class WriteHandler>
|
||||||
auto async_hello (AsyncWriteStream& stream, WriteHandler&& handler);
|
void async_hello (AsyncWriteStream& stream, WriteHandler&& handler)
|
||||||
|
{
|
||||||
|
net::async_write (stream,
|
||||||
|
net::buffer(string_view("Hello, world!")),
|
||||||
|
std::forward<Handler>(handler));
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[heading Concurrency]
|
||||||
|
|
||||||
|
I/O objects such as sockets and streams [*are not thread-safe]. Although
|
||||||
|
it is possible to have more than one operation outstanding (for example,
|
||||||
|
a simultaneous asynchronous read and asynchronous write) the stream object
|
||||||
|
itself may only be accessed from one thread at a time. This means that
|
||||||
|
member functions such as move constructors, destructors, or initiating
|
||||||
|
functions must not be called concurrently. Usually this is accomplished
|
||||||
|
with synchronization primitives such as a
|
||||||
|
[@https://en.cppreference.com/w/cpp/thread/mutex `mutex`],
|
||||||
|
but concurrent network programs need a better way to access shared resources,
|
||||||
|
since acquiring ownership of a mutex could block threads from performing
|
||||||
|
uncontended work. For efficiency, networking adopts a model of using threads
|
||||||
|
without explicit locking by requiring all access to I/O objects to be
|
||||||
|
performed within a
|
||||||
|
[@boost:/doc/html/boost_asio/overview/core/strands.html ['strand]].
|
||||||
|
|
||||||
|
[heading Asynchronous Model]
|
||||||
|
|
||||||
|
Completion handlers are native to networking but cause an inversion of the
|
||||||
|
flow of control. Alternatives to using completion handlers include futures,
|
||||||
|
fibers, coroutines, or user-defined types. Networking supports these
|
||||||
|
alternatives with a feature that provides these hooks for customizing
|
||||||
|
initiating functions:
|
||||||
|
|
||||||
|
* Converting a custom ['CompletionToken] to a "real" handler type
|
||||||
|
|
||||||
|
* Creating the initiating function's result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[/
|
[/
|
||||||
[heading Concurrency Without Locking]
|
The system
|
||||||
|
for customizing the return type of initiating functions and obtaining the
|
||||||
|
actual completion handler from a completion token is known as the
|
||||||
|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf ['Universal Model for Asynchronous Operations]] (N3747).
|
||||||
|
This generic example shows the signature for an initiating function to
|
||||||
|
write some text to a stream:
|
||||||
|
```
|
||||||
|
template <class AsyncWriteStream, class WriteHandler>
|
||||||
|
auto async_hello (AsyncWriteStream& stream, WriteHandler&& handler);
|
||||||
|
```
|
||||||
|
|
||||||
multiple threads calling io_context::run
|
The signature for the initiating function includes a
|
||||||
|
['completion token],
|
||||||
When a composed operation submits intermediate completion handlers for operations used to meet its stated effects, the intermediate handlers must use the same executor as that used for the final completion handler
|
which is a generalization of completion handlers permitting user-defined
|
||||||
This is to avoid accessing the underlying I/O object in ways that violate preconditions
|
types such as futures or coroutines to be substituted as the mechanism by
|
||||||
|
which the results of the asynchronous operation are delivered. The following
|
||||||
[heading Universal Asynchronous Model]
|
statements all call the same function to asynchronously read data from a
|
||||||
|
stream, but use a different method for receiving the results:
|
||||||
A strand provides an additional execution
|
|
||||||
guarantee: function objects submitted to the strand are never executed
|
|
||||||
concurrently by the underlying executor. Strands permit concurrent asynchronous
|
|
||||||
applications to be developed which
|
|
||||||
[@boost:/doc/html/boost_asio/overview/core/strands.html use threads without explicit locking].
|
|
||||||
|
|
||||||
The use of invocable function objects
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[/-----------------------------------------------------------------------------]
|
||||||
|
|
||||||
[heading Using Networking]
|
[heading Using Networking]
|
||||||
|
|
||||||
|
@ -9,8 +9,13 @@
|
|||||||
|
|
||||||
[section:streams Streams]
|
[section:streams Streams]
|
||||||
|
|
||||||
Stream types represent objects capable of performing synchronous or
|
A stream in the context of Beast and networking, represents a full-duplex
|
||||||
asynchronous I/O. They are based on concepts from `boost::asio`.
|
connection between two programs or hosts, where data represented as
|
||||||
|
bytes may be received reliably in the same order they were written.
|
||||||
|
Streams can be support synchronous transfers, asynchronous transfers,
|
||||||
|
or both.
|
||||||
|
|
||||||
|
Stream concepts are based on named requirements in networking:
|
||||||
|
|
||||||
[heading:Stream Stream]
|
[heading:Stream Stream]
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user