boost/beast/core/impl/async_base.hpp
// // 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 <boost/core/exchange.hpp> namespace boost { namespace beast { namespace detail { template<class State, class Allocator> struct allocate_stable_state final : stable_base , boost::empty_value<Allocator> { State value; template<class... Args> explicit allocate_stable_state( Allocator const& alloc, Args&&... args) : boost::empty_value<Allocator>( boost::empty_init_t{}, alloc) , value{std::forward<Args>(args)...} { } void destroy() override { using A = typename allocator_traits< Allocator>::template rebind_alloc< allocate_stable_state>; A a(this->get()); detail::allocator_traits<A>::destroy(a, this); detail::allocator_traits<A>::deallocate(a, this, 1); } }; } // detail template< class Handler, class Executor1, class Allocator, class Function> void asio_handler_invoke( Function&& f, async_base<Handler, Executor1, Allocator>* p) { using net::asio_handler_invoke; asio_handler_invoke(f, p->get_legacy_handler_pointer()); } template< class Handler, class Executor1, class Allocator> void* asio_handler_allocate( std::size_t size, async_base<Handler, Executor1, Allocator>* p) { using net::asio_handler_allocate; return asio_handler_allocate(size, p->get_legacy_handler_pointer()); } template< class Handler, class Executor1, class Allocator> void asio_handler_deallocate( void* mem, std::size_t size, async_base<Handler, Executor1, Allocator>* p) { using net::asio_handler_deallocate; asio_handler_deallocate(mem, size, p->get_legacy_handler_pointer()); } template< class Handler, class Executor1, class Allocator> bool asio_handler_is_continuation( async_base<Handler, Executor1, Allocator>* p) { using net::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 A = typename detail::allocator_traits< allocator_type>::template rebind_alloc< detail::allocate_stable_state< State, allocator_type>>; struct deleter { allocator_type alloc; detail::allocate_stable_state< State, allocator_type>* ptr; ~deleter() { if(ptr) { A a(alloc); detail::allocator_traits<A>::deallocate(a, ptr, 1); } } }; A a(base.get_allocator()); deleter d{base.get_allocator(), nullptr}; d.ptr = detail::allocator_traits<A>::allocate(a, 1); detail::allocator_traits<A>::construct(a, d.ptr, d.alloc, std::forward<Args>(args)...); d.ptr->next_ = base.list_; base.list_ = d.ptr; return boost::exchange(d.ptr, nullptr)->value; } } // beast } // boost #endif