From 8f88f9c3bbaa36b6db632d1a0b1fa5d8424b2c0d Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Sat, 10 Jun 2017 16:00:15 -0700 Subject: [PATCH] Remove extraneous doc file --- doc/x2_0_core.qbk | 725 ---------------------------------------------- 1 file changed, 725 deletions(-) delete mode 100644 doc/x2_0_core.qbk diff --git a/doc/x2_0_core.qbk b/doc/x2_0_core.qbk deleted file mode 100644 index 17f0d6cb..00000000 --- a/doc/x2_0_core.qbk +++ /dev/null @@ -1,725 +0,0 @@ -[/ - Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -] - -[section:core Core Concepts] - -[block ''' - - Working With Asio - Stream Concepts - Buffer Concepts - Asynchronous Utilities - Asynchronous Composed Operation Tutorial - -'''] - -A goal of the library is expose implementation primitives in order that -users may build their own library-like components. These primitives include -traits, buffers, buffer algorithms, and helpers for implementing asynchronous -operations compatible with __Asio__ and described in __N3747__. This section -lists these facilities by group, with descriptions. - -[important - This documentation assumes familiarity with __Asio__. Sample - code and identifiers used throughout are written as if the - following declarations are in effect: - ``` - #include - #include - #include - #include - - using namespace beast; - - boost::asio::io_service ios; - boost::asio::io_service work{ios}; - std::thread t{[&](){ ios.run(); }}; - - error_code ec; - - ``` -] - - - -[heading:asio Working With Asio] - -Beast does not manage sockets, make outgoing connections, accept incoming -connections, or handle any aspect of connection management. In order to -invoke library algorithms it is necessary to first have a connected socket, -SSL stream, or other object which meets the required stream concepts. This -example is provided as a reminder of how to work with sockets: -``` - auto host = "www.example.com"; - boost::asio::ip::tcp::resolver r{ios}; - boost::asio::ip::tcp::socket sock{ios}; - boost::asio::connect(sock, r.resolve( - boost::asio::ip::tcp::resolver::query{host, "http"})); - - // At this point `sock` is a connected to a remote - // host and may be used to perform stream operations. -``` - -Throughout this documentation identifiers with the following names have -special meaning: - -[table Global Variables -[[Name][Description]] -[[ - [@http://www.boost.org/doc/html/boost_asio/reference/io_service.html [*`ios`]] -][ - A variable of type - [@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`] - which is running on one separate thread, and upon which a - [@http://www.boost.org/doc/html/boost_asio/reference/io_service__work.html `boost::asio::io_service::work`] - object has been constructed. -]] -[[ - [@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html [*`sock`]] -][ - A variable of type - [@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html `boost::asio::ip::tcp::socket`] - which has already been connected to a remote host. -]] -[[ - [@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html [*`ssl_sock`]] -][ - A variable of type - [@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html `boost::asio::ssl::stream`] - which is already connected and has handshaked with a remote host. -]] -] - -[heading:streams Stream Concepts] - -A __Stream__ is communication channel where data expressed as octet -buffers is transferred sequentially. Streams are either synchronous -or asynchronous, and may allow reading, writing, or both. Note that -a particular type may model more than one concept. For example, the -Asio types -[@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html `boost::asio::ip::tcp::socket`] -and -[@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html `boost::asio::ssl::stream`] -support everything. All stream algorithms in Beast are declared as -template functions with specific concept requirements chosen from -this list: - -[table Stream Concepts -[[Concept][Description]] -[ - [__SyncReadStream__] - [ - Supports buffer-oriented blocking reads. - ] -][ - [__SyncWriteStream__] - [ - Supports buffer-oriented blocking writes. - ] -][ - [__SyncStream__] - [ - A stream supporting buffer-oriented blocking reads and writes. - ] -][ - [__AsyncReadStream__] - [ - Supports buffer-oriented asynchronous reads. - ] -][ - [__AsyncWriteStream__] - [ - Supports buffer-oriented asynchronous writes. - ] -][ - [__AsyncStream__] - [ - A stream supporting buffer-oriented asynchronous reads and writes. - ] -] -] - -These template metafunctions check whether a given type meets the -requirements for the various stream concepts, and some additional -useful utilities. The library uses these type checks internally -and also provides them as public interfaces so users may use the -same techniques to augment their own code. The use of these type -checks helps provide more concise errors during compilation: - -[table Stream Type Checks -[[Name][Description]] -[[ - [link beast.ref.get_lowest_layer `get_lowest_layer`] -][ - Returns `T::lowest_layer_type` if it exists, else returns `T`. -]] -[[ - [link beast.ref.has_get_io_service `has_get_io_service`] -][ - Determine if the `get_io_service` member function is present, - and returns an __io_service__. -]] -[[ - [link beast.ref.is_async_read_stream `is_async_read_stream`] -][ - Determine if a type meets the requirements of __AsyncReadStream__. -]] -[[ - [link beast.ref.is_async_stream `is_async_stream`] -][ - Determine if a type meets the requirements of both __AsyncReadStream__ - and __AsyncWriteStream__. -]] -[[ - [link beast.ref.is_async_write_stream `is_async_write_stream`] -][ - Determine if a type meets the requirements of __AsyncWriteStream__. -]] -[[ - [link beast.ref.is_completion_handler `is_completion_handler`] -][ - Determine if a type meets the requirements of __CompletionHandler__, - and is callable with a specified signature. -]] -[[ - [link beast.ref.is_sync_read_stream `is_sync_read_stream`] -][ - Determine if a type meets the requirements of __SyncReadStream__. -]] -[[ - [link beast.ref.is_sync_stream `is_sync_stream`] -][ - Determine if a type meets the requirements of both __SyncReadStream__ - and __SyncWriteStream__. -]] -[[ - [link beast.ref.is_sync_write_stream `is_sync_write_stream`] -][ - Determine if a type meets the requirements of __SyncWriteStream__. -]] -] - -Using the type checks with `static_assert` on function or class template -types will provide users with helpful error messages and prevent undefined -behaviors. This example shows how a template function which writes to a -synchronous stream may check its argument: -``` -template -void write_string(SyncWriteStream& stream, string_view s) -{ - static_assert(is_sync_write_stream::value, - "SyncWriteStream requirements not met"); - boost::asio::write(stream, boost::asio::const_buffers_1(s.data(), s.size())); -} -``` - - - -[heading:buffers Buffer Concepts] - -__Asio__ provides the __ConstBufferSequence__ and __MutableBufferSequence__ -concepts, whose models provide ranges of buffers, as well as the __streambuf__ -class which encapsulates memory storage that may be automatically resized as -required, where the memory is divided into an input sequence followed by an -output sequence. The Networking TS (__N4588__) generalizes the `streambuf` -interface into the __DynamicBuffer__ concept. Beast algorithms which require -resizable buffers accept as parameters dynamic buffer objects. These -metafunctions check types against these buffer concepts: - -[table Buffer Type Checks -[[Name][Description]] -[[ - [link beast.ref.is_const_buffer_sequence `is_const_buffer_sequence`] -][ - Determine if a type meets the requirements of __ConstBufferSequence__. -]] -[[ - [link beast.ref.is_mutable_buffer_sequence `is_mutable_buffer_sequence`] -][ - Determine if a type meets the requirements of __MutableBufferSequence__. -]] -[[ - [link beast.ref.is_dynamic_buffer `is_dynamic_buffer`] -][ - Determine if a type meets the requirements of __DynamicBuffer__. -]] -] - -To suit various needs, several implementation of dynamic buffer are available: - -[table Dynamic Buffer Implementations -[[Name][Description]] -[[ - [link beast.ref.buffers_adapter `buffers_adapter`] -][ - This wrapper adapts any __MutableBufferSequence__ into a - __DynamicBuffer__ with an upper limit on the total size of the input and - output areas equal to the size of the underlying mutable buffer sequence. - The implementation does not perform heap allocations. -]] -[[ - [link beast.ref.flat_buffer `flat_buffer`] - [link beast.ref.basic_flat_buffer `basic_flat_buffer`] -][ - Guarantees that input and output areas are buffer sequences with - length one. Upon construction an optional upper limit to the total - size of the input and output areas may be set. The basic container - supports the standard allocator model. -]] -[[ - [link beast.ref.multi_buffer `multi_buffer`] - [link beast.ref.basic_multi_buffer `basic_multi_buffer`] -][ - Uses a sequence of one or more character arrays of varying sizes. - Additional character array objects are appended to the sequence to - accommodate changes in the size of the character sequence. The basic - container supports the standard allocator model. -]] -[[ - [link beast.ref.static_buffer `static_buffer`] - [link beast.ref.static_buffer `static_buffer_n`] -][ - Provides the facilities of a dynamic buffer, subject to an upper - limit placed on the total size of the input and output areas defined - by a constexpr template parameter. The storage for the sequences are - kept in the class; the implementation does not perform heap allocations. -]] -] - -Network applications frequently need to manipulate buffer sequences. To -facilitate working with buffers the library treats these sequences as -a special type of range. Algorithms and wrappers are provided which -transform these buffer sequences ranges efficiently using lazy evaluation. -No memory allocations are used in the transformations; instead, they -create lightweight iterators over the existing, unmodified memory -buffers. The lifetime of the transformed buffers is retained by the -caller; ownership is not transferred. - -[table Buffer Algorithms -[[Name][Description]] -[[ - [link beast.ref.buffer_cat `buffer_cat`] -][ - This functions returns a new buffer sequence which, when iterated, - traverses the sequence which would be formed if all of the input buffer - sequences were concatenated. With this routine, multiple calls to a - stream's `write_some` function may be combined into one, eliminating - expensive system calls. -]] -[[ - [link beast.ref.buffer_cat_view `buffer_cat_view`] -][ - This class represents the buffer sequence formed by concatenating - two or more buffer sequences. This is type of object returned by - [link beast.ref.buffer_cat `buffer_cat`]. -]] -[[ - [link beast.ref.buffer_prefix `buffer_prefix`] -][ - This function returns a new buffer or buffer sequence which represents - a prefix of the original buffers. -]] -[[ - [link beast.ref.buffer_prefix_view `buffer_prefix_view`] -][ - This class represents the buffer sequence formed from a prefix of - an existing buffer sequence. This is the type of buffer returned by - [link beast.ref.buffer_prefix `buffer_prefix`]. -]] -[[ - [link beast.ref.consuming_buffers `consuming_buffers`] -][ - This class wraps the underlying memory of an existing buffer sequence - and presents a suffix of the original sequence. The length of the suffix - may be progressively shortened. This lets callers work with sequential - increments of a buffer sequence. -]] -] - -These two functions facilitate buffer interoperability with standard -output streams. - -[table Buffer Output Streams -[[Name][Description]] -[[ - [link beast.ref.buffers `buffers`] -][ - This function wraps a __ConstBufferSequence__ so it may be - used with `operator<<` and `std::ostream`. -]] -[[ - [link beast.ref.ostream `ostream`] -][ - This function returns a `std::ostream` which wraps a dynamic buffer. - Characters sent to the stream using `operator<<` is stored in the - dynamic buffer. -]] -] - - - -[heading:async Asynchronous Utilities] - -Asynchronous operations are started by calling a free function or member -function known as an ['asynchronous initiation function]. The initiation -function accepts parameters specific to the operation as well as a "completion -token." This token is either a completion handler, or another type allowing for -customization of how the result of the asynchronous operation is conveyed to -callers. __Asio__ allows the special completion tokens __use_future__ and -objects of type __yield_context__ to allow callers to specify the use of futures -and coroutines respectively. This system, where the return value and method of -indicating completion may be customize at the call site of the asynchronous -initiation function, is known as the ['Extensible Asynchronous Model] described -in __N3747__, and built-in to __N4588__. - -[note - A full explanation of completion handlers, the Extensible Asynchronous - Model and how these asynchronous interfaces are used is beyond the - scope of this document. Interested readers should consult the - __Asio__ documentation. -] - -Since the interfaces provided here are low level, authors of libraries -may wish to create higher level interfaces using the primitives found -in this library. Non-trivial applications will want to provide their own -asynchronous initiation functions which perform a series of other, -intermediate asynchronous operations before invoking the final completion -handler. The set of intermediate actions produced by calling an initiation -function is known as a ['composed operation]. To ensure full interoperability -and well-defined behavior, __Asio__ imposes requirements on the implementation -of composed operations. A number of useful classes and macros to facilitate -the development of composed operations and the associated asynchronous -initiation functions used to launch them are available: - -[table Asynchronous Helpers -[[Name][Description]] -[[ - [link beast.ref.async_completion `async_completion`] -][ - This class aggregates the completion handler customization point and - the asynchronous initiation function return value customization point - into a single object which exposes the appropriate output types for the - given input types, and also contains boilerplate that is necessary to - implement an initiation function using the Extensible Model. -]] -[[ - [link beast.ref.async_return_type `async_return_type`] -][ - This template alias determines the return value of an asynchronous - initiation function given the completion token and signature. It is used - by asynchronous initiation functions to meet the requirements of the - Extensible Asynchronous Model. -]] -[[ - [link beast.ref.bind_handler `bind_handler`] -][ - This function returns a new, nullary completion handler which when - invoked with no arguments invokes the original completion handler with a - list of bound arguments. The invocation is made from the same implicit - or explicit strand as that which would be used to invoke the original - handler. This is accomplished by using the correct overload of - `asio_handler_invoke` associated with the original completion handler. - -]] -[[ - [link beast.ref.handler_alloc `handler_alloc`] -][ - This class meets the requirements of [*Allocator], and uses any custom - memory allocation and deallocation hooks associated with a given handler. - It is useful for when a composed operation requires temporary dynamic - allocations to achieve its result. Memory allocated using this allocator - must be freed before the final completion handler is invoked. -]] -[[ - [link beast.ref.handler_ptr `handler_ptr`] -][ - This is a smart pointer container used to manage the internal state of a - composed operation. It is useful when the state is non trivial. For example - when the state has non-copyable or expensive to copy types. The container - takes ownership of the final completion handler, and provides boilerplate - to invoke the final handler in a way that also deletes the internal state. - The internal state is allocated using the final completion handler's - associated allocator, benefiting from all handler memory management - optimizations transparently. -]] -[[ - [link beast.ref.handler_type `handler_type`] -][ - This template alias converts a completion token and signature to the - correct completion handler type. It is used in the implementation of - asynchronous initiation functions to meet the requirements of the - Extensible Asynchronous Model. -]] -] - - - -[section:tutorial Asynchronous Composed Operation Tutorial] - -To illustrate the usage of the asynchronous helpers in the core section of -this library, we will develop a simple asynchronous composed operation called -[*echo]. This operation will read up to the first newline on a stream, and -then write the same line including the newline back on the stream. - -First we define the input parameters and results, then declare our initiation -function. For our echo operation the only inputs are the stream and the -completion token. The output is the error code which is usually included in -all completion handler signatures. - -``` - #include - #include - #include - #include - #include - - // Read a line and echo it back - // - template - beast::async_return_type - async_echo(AsyncStream& stream, CompletionToken&& token) -``` - -Now that we have a declaration, we will define the body of the function. We -want to achieve the following goals: perform static type checking on the input -parameters, set up the return value as per __N3747__, and launch the composed -operation by constructing the object and invoking it. - -``` - template - class echo_op; // This is our composed operation implementation - - // Read a line and echo it back - // - template - beast::async_return_type - async_echo(AsyncStream& stream, CompletionToken&& token) - { - // Make sure stream meets the requirements. We use static_assert - // to cause a friendly message instead of an error novel. - // - static_assert(beast::is_async_stream::value, - "AsyncStream requirements not met"); - - // This helper manages some of the handler's lifetime and - // uses the result and handler specializations associated with - // the completion token to help customize the return value. - // - beast::async_completion init{token}; - - // Create the composed operation and launch it. This is a constructor - // call followed by invocation of operator(). We use handler_type - // to convert the completion token into the correct handler type, - // allowing user defined specializations of the async result template - // to take effect. - // - echo_op>{ - stream, init.completion_handler}(beast::error_code{}, 0); - - // This hook lets the caller see a return value when appropriate. - // For example this might return std::future if - // CompletionToken is boost::asio::use_future, or this might - // return an error code if CompletionToken specifies a coroutine. - // - return init.result.get(); - } -``` - -The initiation function contains a few relatively simple parts. There is the -customization of the return value type, static type checking, building the -return value type using the helper, and creating and launching the composed -operation object. The [*`echo_op`] object does most of the work here, and has -a somewhat non-trivial structure. This structure is necessary to meet the -stringent requirements of composed operations (described in more detail in -the __Asio__ documentation). We will touch on these requirements without -explaining them in depth. - -First we will create boilerplate which is present in all composed operations -written in this style: - -``` - // This composed operation reads a line of input and echoes it back. - // - template - class echo_op - { - // This holds all of the state information required by the operation. - struct state - { - // The stream to read and write to - AsyncStream& stream; - - // Indicates what step in the operation's state machine - // to perform next, starting from zero. - int step = 0; - - // The buffer used to hold the input and output data. - // Note that we use a custom allocator for performance, - // this allows the implementation of the io_service to - // make efficient re-use of memory allocated by composed - // operations during continuations. - // - boost::asio::basic_streambuf> buffer; - - // handler_ptr requires that the first parameter to the - // contained object constructor is a reference to the - // managed final completion handler. - // - explicit state(Handler& handler, AsyncStream& stream_) - : stream(stream_) - , buffer((std::numeric_limits::max)(), - beast::handler_alloc{handler}) - { - } - }; - - // This smart pointer container allocates our state using the - // memory allocation hooks associated with the final completion - // handler, manages the lifetime of that handler for us, and - // enforces the destroy-before-invocation requirement on memory - // allocated using the hooks. - // - beast::handler_ptr p_; - - public: - // Boost.Asio requires that handlers are CopyConstructible. - // In some cases, it takes advantage of handlers that are - // MoveConstructible. This operation supports both. - // - echo_op(echo_op&&) = default; - echo_op(echo_op const&) = default; - - // The constructor simply creates our state variables in - // the smart pointer container. - // - template - echo_op(AsyncStream& stream, DeducedHandler&& handler) - : p_(std::forward(handler), stream) - { - } - - // Determines if the next asynchronous operation represents a - // continuation of the asynchronous flow of control associated - // with the final handler. If we are past step one, it means - // we have performed an asynchronous operation therefore any - // subsequent operation would represent a continuation. - // Otherwise, we propagate the handler's associated value of - // is_continuation. Getting this right means the implementation - // may schedule the invokation of the invoked functions more - // efficiently. - // - friend bool asio_handler_is_continuation(echo_op* op) - { - // This next call is structured to permit argument - // dependent lookup to take effect. - using boost::asio::asio_handler_is_continuation; - - // Always use std::addressof to pass the pointer to the handler, - // otherwise an unwanted overload of operator& may be called instead. - return op->p_->step > 1 || - asio_handler_is_continuation(std::addressof(op->p_.handler())); - } - - // Handler hook forwarding. These free functions invoke the hooks - // associated with the final completion handler. In effect, they - // make the Asio implementation treat our composed operation the - // same way it would treat the final completion handler for the - // purpose of memory allocation and invocation. - // - // Our implementation just passes through the call to the hook - // associated with the final handler. - - friend void* asio_handler_allocate(std::size_t size, echo_op* op) - { - using boost::asio::asio_handler_allocate; - return asio_handler_allocate(size, std::addressof(op->p_.handler())); - } - - friend void asio_handler_deallocate(void* p, std::size_t size, echo_op* op) - { - using boost::asio::asio_handler_deallocate; - return asio_handler_deallocate(p, size, std::addressof(op->p_.handler())); - } - - template - friend void asio_handler_invoke(Function&& f, echo_op* op) - { - using boost::asio::asio_handler_invoke; - return asio_handler_invoke(f, std::addressof(op->p_.handler())); - } - - // Our main entry point. This will get called as our - // intermediate operations complete. Definition below. - // - void operator()(beast::error_code ec, std::size_t bytes_transferred); - }; -``` - -We have the common boilerplate for a composed operation and now we just need -to implement the function call operator. Our strategy is to make our composed -object meet the requirements of a completion handler by being copyable (also -movable), and by providing the function call operator with the correct -signature. Rather than using `std::bind` or `boost::bind`, which destroys -the type information and therefore breaks the allocation and invocation -hooks, we will simply pass `std::move(*this)` as the completion handler -parameter for any operations that we initiate. For the move to work correctly, -care must be taken to ensure that no access to data members are made after the -move takes place. Here is the implementation of the function call operator for -this echo operation: -``` - // We are callable with the signature void(error_code, bytes_transferred), - // allowing `*this` to be used as both a ReadHandler and a WriteHandler. - // - template - void echo_op:: - operator()(beast::error_code ec, std::size_t bytes_transferred) - { - // Store a reference to our state. The address of the state won't - // change, and this solves the problem where dereferencing the - // data member is undefined after a move. - auto& p = *p_; - - // Now perform the next step in the state machine - switch(ec ? 2 : p.step) - { - // initial entry - case 0: - // read up to the first newline - p.step = 1; - return boost::asio::async_read_until(p.stream, p.buffer, "\n", std::move(*this)); - - case 1: - // write everything back - p.step = 2; - // async_read_until could have read past the newline, - // use buffer_prefix to make sure we only send one line - return boost::asio::async_write(p.stream, - beast::buffer_prefix(bytes_transferred, p.buffer.data()), std::move(*this)); - - case 2: - p.buffer.consume(bytes_transferred); - break; - } - - // Invoke the final handler. If we wanted to pass any arguments - // which come from our state, they would have to be moved to the - // stack first, since the `handler_ptr` guarantees that the state - // is destroyed before the handler is invoked. - // - p_.invoke(ec); - return; - } -``` - -A complete, runnable version of this example may be found in the examples -directory. - -[endsect] - - - -[endsect]