Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http
8 : //
9 :
10 : #ifndef BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP
11 : #define BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP
12 :
13 : #include <boost/config.hpp>
14 :
15 : namespace boost {
16 : namespace http {
17 : namespace detail {
18 :
19 : #if defined(BOOST_MSVC)
20 : #pragma warning(push)
21 : #pragma warning(disable : 4324) /* structure was padded due to __declspec(align()) */
22 : #endif
23 :
24 : struct workspace::any
25 : {
26 : any* next = nullptr;
27 :
28 : BOOST_HTTP_DECL
29 : virtual ~any() = 0;
30 : };
31 :
32 : template<class U>
33 : struct alignas(::max_align_t)
34 : workspace::any_impl : any
35 : {
36 : U u;
37 :
38 : any_impl(any_impl const&) = delete;
39 : any_impl(any_impl&&) = delete;
40 :
41 : template<class... Args>
42 : explicit any_impl(Args&&... args)
43 : : u(std::forward<Args>(args)...)
44 : {
45 : }
46 : };
47 :
48 : struct workspace::undo
49 : {
50 : explicit
51 224 : undo(workspace& ws0) noexcept
52 224 : : ws_(ws0)
53 224 : , head_(ws0.head_)
54 : {
55 224 : }
56 :
57 224 : ~undo()
58 : {
59 224 : if(head_)
60 0 : ws_.head_ = head_;
61 224 : }
62 :
63 : void
64 224 : commit() noexcept
65 : {
66 224 : head_ = nullptr;
67 224 : }
68 :
69 : private:
70 : workspace& ws_;
71 : unsigned char* head_;
72 : };
73 :
74 : template<class T>
75 : constexpr
76 : std::size_t
77 : workspace::
78 : space_needed()
79 : {
80 : using U = typename std::decay<T>::type;
81 :
82 : static_assert(
83 : alignof(U) <= alignof(::max_align_t),
84 : "Overaligned types not supported");
85 :
86 : return sizeof(any_impl<U>);
87 : }
88 :
89 : template<class T, class... Args>
90 : auto
91 : workspace::
92 : emplace(Args&&... args) ->
93 : typename std::decay<T>::type&
94 : {
95 : static_assert(
96 : alignof(T) <= alignof(::max_align_t),
97 : "Overaligned types not supported");
98 :
99 : using U = any_impl<typename
100 : std::decay<T>::type>;
101 :
102 : undo u(*this);
103 : auto prev_head = head_;
104 : head_ = bump_down(sizeof(U), alignof(U));
105 : auto p = ::new(head_) U(
106 : std::forward<Args>(args)...);
107 : u.commit();
108 : p->next = reinterpret_cast<
109 : any*>(prev_head);
110 : return p->u;
111 : }
112 :
113 : template<class T>
114 : T*
115 224 : workspace::
116 : push_array(
117 : std::size_t n,
118 : T const& t)
119 : {
120 : struct alignas(::max_align_t)
121 : U : any
122 : {
123 : std::size_t n_ = 0;
124 :
125 224 : U() = default;
126 224 : ~U()
127 : {
128 224 : for(std::size_t i = n_;
129 896 : i-- > 0;)
130 672 : data()[i].~T();
131 448 : }
132 :
133 224 : U( std::size_t n,
134 : T const& t)
135 224 : : U()
136 : {
137 896 : while(n_ < n)
138 : {
139 672 : new(&data()[n_]) T(t);
140 672 : ++n_;
141 : }
142 224 : }
143 :
144 1568 : T* data() noexcept
145 : {
146 : return reinterpret_cast<
147 1568 : T*>(this + 1);
148 : }
149 : };
150 :
151 224 : undo u(*this);
152 224 : auto prev_head = head_;
153 448 : head_ = bump_down(
154 224 : sizeof(U) + n * sizeof(T),
155 : alignof(::max_align_t));
156 224 : auto p = ::new(head_) U(n, t);
157 224 : u.commit();
158 224 : p->next = reinterpret_cast<
159 : any*>(prev_head);
160 448 : return p->data();
161 224 : }
162 :
163 : #if defined(BOOST_MSVC)
164 : #pragma warning(pop) /* C4324 */
165 : #endif
166 :
167 : } // detail
168 : } // http
169 : } // boost
170 :
171 : #endif
|