]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/example/http/server/fast/fields_alloc.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / example / http / server / fast / fields_alloc.hpp
1 //
2 // Copyright (c) 2016-2017 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_EXAMPLE_FIELDS_ALLOC_HPP
11 #define BOOST_BEAST_EXAMPLE_FIELDS_ALLOC_HPP
12
13 #include <boost/throw_exception.hpp>
14 #include <cstdlib>
15 #include <memory>
16 #include <stdexcept>
17
18 namespace detail {
19
20 struct static_pool
21 {
22 std::size_t size_;
23 std::size_t refs_ = 1;
24 std::size_t count_ = 0;
25 char* p_;
26
27 char*
28 end()
29 {
30 return reinterpret_cast<char*>(this+1) + size_;
31 }
32
33 explicit
34 static_pool(std::size_t size)
35 : size_(size)
36 , p_(reinterpret_cast<char*>(this+1))
37 {
38 }
39
40 public:
41 static
42 static_pool&
43 construct(std::size_t size)
44 {
45 auto p = new char[sizeof(static_pool) + size];
46 return *(new(p) static_pool{size});
47 }
48
49 static_pool&
50 share()
51 {
52 ++refs_;
53 return *this;
54 }
55
56 void
57 destroy()
58 {
59 if(refs_--)
60 return;
61 this->~static_pool();
62 delete[] reinterpret_cast<char*>(this);
63 }
64
65 void*
66 alloc(std::size_t n)
67 {
68 auto last = p_ + n;
69 if(last >= end())
70 BOOST_THROW_EXCEPTION(std::bad_alloc{});
71 ++count_;
72 auto p = p_;
73 p_ = last;
74 return p;
75 }
76
77 void
78 dealloc()
79 {
80 if(--count_)
81 return;
82 p_ = reinterpret_cast<char*>(this+1);
83 }
84 };
85
86 } // detail
87
88 /** A non-thread-safe allocator optimized for @ref basic_fields.
89
90 This allocator obtains memory from a pre-allocated memory block
91 of a given size. It does nothing in deallocate until all
92 previously allocated blocks are deallocated, upon which it
93 resets the internal memory block for re-use.
94
95 To use this allocator declare an instance persistent to the
96 connection or session, and construct with the block size.
97 A good rule of thumb is 20% more than the maximum allowed
98 header size. For example if the application only allows up
99 to an 8,000 byte header, the block size could be 9,600.
100
101 Then, for every instance of `message` construct the header
102 with a copy of the previously declared allocator instance.
103 */
104 template<class T>
105 struct fields_alloc
106 {
107 detail::static_pool& pool_;
108
109 public:
110 using value_type = T;
111 using is_always_equal = std::false_type;
112 using pointer = T*;
113 using reference = T&;
114 using const_pointer = T const*;
115 using const_reference = T const&;
116 using size_type = std::size_t;
117 using difference_type = std::ptrdiff_t;
118
119 template<class U>
120 struct rebind
121 {
122 using other = fields_alloc<U>;
123 };
124
125 explicit
126 fields_alloc(std::size_t size)
127 : pool_(detail::static_pool::construct(size))
128 {
129 }
130
131 fields_alloc(fields_alloc const& other)
132 : pool_(other.pool_.share())
133 {
134 }
135
136 template<class U>
137 fields_alloc(fields_alloc<U> const& other)
138 : pool_(other.pool_.share())
139 {
140 }
141
142 ~fields_alloc()
143 {
144 pool_.destroy();
145 }
146
147 value_type*
148 allocate(size_type n)
149 {
150 return static_cast<value_type*>(
151 pool_.alloc(n * sizeof(T)));
152 }
153
154 void
155 deallocate(value_type*, size_type)
156 {
157 pool_.dealloc();
158 }
159
160 #if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
161 template<class U, class... Args>
162 void
163 construct(U* ptr, Args&&... args)
164 {
165 ::new((void*)ptr) U(std::forward<Args>(args)...);
166 }
167
168 template<class U>
169 void
170 destroy(U* ptr)
171 {
172 ptr->~U();
173 }
174 #endif
175
176 template<class U>
177 friend
178 bool
179 operator==(
180 fields_alloc const& lhs,
181 fields_alloc<U> const& rhs)
182 {
183 return &lhs.pool_ == &rhs.pool_;
184 }
185
186 template<class U>
187 friend
188 bool
189 operator!=(
190 fields_alloc const& lhs,
191 fields_alloc<U> const& rhs)
192 {
193 return ! (lhs == rhs);
194 }
195 };
196
197 #endif