Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.
PrevUpHomeNext

async_base

Base class to assist writing composed operations.

Synopsis

Defined in header <boost/beast/core/async_base.hpp>

template<
    class Handler,
    class Executor1,
    class Allocator = std::allocator<void>>
class async_base
Types

Name

Description

allocator_type

The type of allocator associated with this object.

executor_type

The type of executor associated with this object.

Member Functions

Name

Description

async_base [constructor]

Constructor.

Move Constructor.

complete

Invoke the final completion handler, maybe using post.

complete_now

Invoke the final completion handler.

get_allocator

Returns the allocator associated with this object.

get_executor

Returns the executor associated with this object.

handler

Returns the handler associated with this object.

operator=

release_handler

Returns ownership of the handler associated with this object.

~async_base [destructor]

Description

A function object submitted to intermediate initiating functions during a composed operation may derive from this type to inherit all of the boilerplate to forward the executor, allocator, and legacy customization points associated with the completion handler invoked at the end of the composed operation. The composed operation must be typical; that is, associated with one executor of an I/O object, and invoking a caller-provided completion handler when the operation is finished. Classes derived from async_base will acquire these properties:

Example

The following code demonstrates how async_base may be be used to assist authoring an asynchronous initiating function, by providing all of the boilerplate to manage the final completion handler in a way that maintains the allocator and executor associations:

// Asynchronously read into a buffer until the buffer is full, or an error occurs
template<class AsyncReadStream, class ReadHandler>
typename net::async_result<ReadHandler, void(error_code, std::size_t)>::return_type
async_read(AsyncReadStream& stream, net::mutable_buffer buffer, ReadHandler&& handler)
{
    using handler_type = BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t));
    using base_type = async_base<handler_type, typename AsyncReadStream::executor_type>;

    struct op : base_type
    {
        AsyncReadStream& stream_;
        net::mutable_buffer buffer_;
        std::size_t total_bytes_transferred_;

        op(
            AsyncReadStream& stream,
            net::mutable_buffer buffer,
            handler_type& handler)
            : base_type(std::move(handler), stream.get_executor())
            , stream_(stream)
            , buffer_(buffer)
            , total_bytes_transferred_(0)
        {
            (*this)({}, 0, false); // start the operation
        }

        void operator()(error_code ec, std::size_t bytes_transferred, bool is_continuation = true)
        {
            // Adjust the count of bytes and advance our buffer
            total_bytes_transferred_ += bytes_transferred;
            buffer_ = buffer_ + bytes_transferred;

            // Keep reading until buffer is full or an error occurs
            if(! ec && buffer_.size() > 0)
                return stream_.async_read_some(buffer_, std::move(*this));

            // Call the completion handler with the result. If `is_continuation` is
            // false, which happens on the first time through this function, then
            // `net::post` will be used to call the completion handler, otherwise
            // the completion handler will be invoked directly.

            this->complete(is_continuation, ec, total_bytes_transferred_);
        }
    };

    net::async_completion<ReadHandler, void(error_code, std::size_t)> init{handler};
    op(stream, buffer, init.completion_handler);
    return init.result.get();
}

Data members of composed operations implemented as completion handlers do not have stable addresses, as the composed operation object is move constructed upon each call to an initiating function. For most operations this is not a problem. For complex operations requiring stable temporary storage, the class stable_async_base is provided which offers additional functionality:

Temporary Storage Example

The following example demonstrates how a composed operation may store a temporary object.

Template Parameters

Type

Description

Handler

The type of the completion handler to store. This type must meet the requirements of CompletionHandler.

Executor1

The type of the executor used when the handler has no associated executor. An instance of this type must be provided upon construction. The implementation will maintain an executor work guard and a copy of this instance.

Allocator

The allocator type to use if the handler does not have an associated allocator. If this parameter is omitted, then std::allocator<void> will be used. If the specified allocator is not default constructible, an instance of the type must be provided upon construction.

See Also

stable_async_base


PrevUpHomeNext