• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_CORE_IMPL_ASYNC_BASE_HPP
11 #define BOOST_BEAST_CORE_IMPL_ASYNC_BASE_HPP
12 
13 #include <boost/core/exchange.hpp>
14 
15 namespace boost {
16 namespace beast {
17 
18 namespace detail {
19 
20 template<class State, class Allocator>
21 struct allocate_stable_state final
22     : stable_base
23     , boost::empty_value<Allocator>
24 {
25     State value;
26 
27     template<class... Args>
28     explicit
allocate_stable_stateboost::beast::detail::allocate_stable_state29     allocate_stable_state(
30         Allocator const& alloc,
31         Args&&... args)
32         : boost::empty_value<Allocator>(
33             boost::empty_init_t{}, alloc)
34         , value{std::forward<Args>(args)...}
35     {
36     }
37 
destroyboost::beast::detail::allocate_stable_state38     void destroy() override
39     {
40         using A = typename allocator_traits<
41             Allocator>::template rebind_alloc<
42                 allocate_stable_state>;
43 
44         A a(this->get());
45         auto* p = this;
46         p->~allocate_stable_state();
47         a.deallocate(p, 1);
48     }
49 };
50 
51 } // detail
52 
53 template<
54     class Handler,
55     class Executor1,
56     class Allocator,
57     class Function>
58 boost::asio::asio_handler_invoke_is_deprecated
asio_handler_invoke(Function && f,async_base<Handler,Executor1,Allocator> * p)59 asio_handler_invoke(
60     Function&& f,
61     async_base<Handler, Executor1, Allocator>* p)
62 {
63     using boost::asio::asio_handler_invoke;
64     return asio_handler_invoke(f,
65         p->get_legacy_handler_pointer());
66 }
67 
68 template<
69     class Handler,
70     class Executor1,
71     class Allocator>
72 boost::asio::asio_handler_allocate_is_deprecated
asio_handler_allocate(std::size_t size,async_base<Handler,Executor1,Allocator> * p)73 asio_handler_allocate(
74     std::size_t size,
75     async_base<Handler, Executor1, Allocator>* p)
76 {
77     using boost::asio::asio_handler_allocate;
78     return asio_handler_allocate(size,
79         p->get_legacy_handler_pointer());
80 }
81 
82 template<
83     class Handler,
84     class Executor1,
85     class Allocator>
86 boost::asio::asio_handler_deallocate_is_deprecated
asio_handler_deallocate(void * mem,std::size_t size,async_base<Handler,Executor1,Allocator> * p)87 asio_handler_deallocate(
88     void* mem, std::size_t size,
89     async_base<Handler, Executor1, Allocator>* p)
90 {
91     using boost::asio::asio_handler_deallocate;
92     return asio_handler_deallocate(mem, size,
93         p->get_legacy_handler_pointer());
94 }
95 
96 template<
97     class Handler,
98     class Executor1,
99     class Allocator>
100 bool
asio_handler_is_continuation(async_base<Handler,Executor1,Allocator> * p)101 asio_handler_is_continuation(
102     async_base<Handler, Executor1, Allocator>* p)
103 {
104     using boost::asio::asio_handler_is_continuation;
105     return asio_handler_is_continuation(
106         p->get_legacy_handler_pointer());
107 }
108 
109 template<
110     class State,
111     class Handler,
112     class Executor1,
113     class Allocator,
114     class... Args>
115 State&
allocate_stable(stable_async_base<Handler,Executor1,Allocator> & base,Args &&...args)116 allocate_stable(
117     stable_async_base<
118         Handler, Executor1, Allocator>& base,
119     Args&&... args)
120 {
121     using allocator_type = typename stable_async_base<
122         Handler, Executor1, Allocator>::allocator_type;
123     using state = detail::allocate_stable_state<
124         State, allocator_type>;
125     using A = typename detail::allocator_traits<
126         allocator_type>::template rebind_alloc<state>;
127 
128     struct deleter
129     {
130         allocator_type alloc;
131         state* ptr;
132 
133         ~deleter()
134         {
135             if(ptr)
136             {
137                 A a(alloc);
138                 a.deallocate(ptr, 1);
139             }
140         }
141     };
142 
143     A a(base.get_allocator());
144     deleter d{base.get_allocator(), a.allocate(1)};
145     ::new(static_cast<void*>(d.ptr))
146         state(d.alloc, std::forward<Args>(args)...);
147     d.ptr->next_ = base.list_;
148     base.list_ = d.ptr;
149     return boost::exchange(d.ptr, nullptr)->value;
150 }
151 
152 } // beast
153 } // boost
154 
155 #endif
156