// // Copyright (c) 2016-2019 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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_CORE_IMPL_ASYNC_BASE_HPP #define BOOST_BEAST_CORE_IMPL_ASYNC_BASE_HPP #include namespace boost { namespace beast { namespace detail { template struct allocate_stable_state final : stable_base , boost::empty_value { State value; template explicit allocate_stable_state( Allocator const& alloc, Args&&... args) : boost::empty_value( boost::empty_init_t{}, alloc) , value{std::forward(args)...} { } void destroy() override { using A = typename allocator_traits< Allocator>::template rebind_alloc< allocate_stable_state>; A a(this->get()); auto* p = this; p->~allocate_stable_state(); a.deallocate(p, 1); } }; } // detail template< class Handler, class Executor1, class Allocator> bool asio_handler_is_continuation( async_base* p) { using boost::asio::asio_handler_is_continuation; return asio_handler_is_continuation( p->get_legacy_handler_pointer()); } template< class State, class Handler, class Executor1, class Allocator, class... Args> State& allocate_stable( stable_async_base< Handler, Executor1, Allocator>& base, Args&&... args) { using allocator_type = typename stable_async_base< Handler, Executor1, Allocator>::allocator_type; using state = detail::allocate_stable_state< State, allocator_type>; using A = typename detail::allocator_traits< allocator_type>::template rebind_alloc; struct deleter { allocator_type alloc; state* ptr; ~deleter() { if(ptr) { A a(alloc); a.deallocate(ptr, 1); } } }; A a(base.get_allocator()); deleter d{base.get_allocator(), a.allocate(1)}; ::new(static_cast(d.ptr)) state(d.alloc, std::forward(args)...); d.ptr->next_ = base.list_; base.list_ = d.ptr; return boost::exchange(d.ptr, nullptr)->value; } } // beast } // boost #endif