include/boost/http/detail/impl/workspace.hpp

97.1% Lines (34/35) 100.0% Functions (8/8)
include/boost/http/detail/impl/workspace.hpp
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2019 Vinnie Falco ([email protected])
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 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 ws_.head_ = head_;
61 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
172