TLA 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 HIT 159 : undo(workspace& ws0) noexcept
52 159 : : ws_(ws0)
53 159 : , head_(ws0.head_)
54 : {
55 159 : }
56 :
57 159 : ~undo()
58 : {
59 159 : if(head_)
60 MIS 0 : ws_.head_ = head_;
61 HIT 159 : }
62 :
63 : void
64 159 : commit() noexcept
65 : {
66 159 : head_ = nullptr;
67 159 : }
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 159 : 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 159 : U() = default;
126 159 : ~U()
127 : {
128 159 : for(std::size_t i = n_;
129 636 : i-- > 0;)
130 477 : data()[i].~T();
131 318 : }
132 :
133 159 : U( std::size_t n,
134 : T const& t)
135 159 : : U()
136 : {
137 636 : while(n_ < n)
138 : {
139 477 : new(&data()[n_]) T(t);
140 477 : ++n_;
141 : }
142 159 : }
143 :
144 1113 : T* data() noexcept
145 : {
146 : return reinterpret_cast<
147 1113 : T*>(this + 1);
148 : }
149 : };
150 :
151 159 : undo u(*this);
152 159 : auto prev_head = head_;
153 318 : head_ = bump_down(
154 159 : sizeof(U) + n * sizeof(T),
155 : alignof(::max_align_t));
156 159 : auto p = ::new(head_) U(n, t);
157 159 : u.commit();
158 159 : p->next = reinterpret_cast<
159 : any*>(prev_head);
160 318 : return p->data();
161 159 : }
162 :
163 : #if defined(BOOST_MSVC)
164 : #pragma warning(pop) /* C4324 */
165 : #endif
166 :
167 : } // detail
168 : } // http
169 : } // boost
170 :
171 : #endif
|