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

97.9% Lines (46/47) 100.0% Functions (14/14) 72.7% Branches (8/11)
libs/http/include/boost/http/detail/impl/workspace.hpp
Line Branch Hits 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 10 explicit any_impl(Args&&... args)
43 10 : u(std::forward<Args>(args)...)
44 {
45 10 }
46 };
47
48 struct workspace::undo
49 {
50 explicit
51 101 undo(workspace& ws0) noexcept
52 101 : ws_(ws0)
53 101 , head_(ws0.head_)
54 {
55 101 }
56
57 101 ~undo()
58 {
59
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
101 if(head_)
60 ws_.head_ = head_;
61 101 }
62
63 void
64 101 commit() noexcept
65 {
66 101 head_ = nullptr;
67 101 }
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 10 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 10 undo u(*this);
103 10 auto prev_head = head_;
104
1/1
✓ Branch 1 taken 10 times.
10 head_ = bump_down(sizeof(U), alignof(U));
105
1/3
✓ Branch 3 taken 10 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
10 auto p = ::new(head_) U(
106 std::forward<Args>(args)...);
107 10 u.commit();
108 10 p->next = reinterpret_cast<
109 any*>(prev_head);
110 10 return p->u;
111 10 }
112
113 template<class T>
114 T*
115 91 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 91 U() = default;
126 91 ~U()
127 {
128 91 for(std::size_t i = n_;
129
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 91 times.
382 i-- > 0;)
130 291 data()[i].~T();
131 182 }
132
133 91 U( std::size_t n,
134 T const& t)
135 91 : U()
136 {
137
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 91 times.
382 while(n_ < n)
138 {
139 291 new(&data()[n_]) T(t);
140 291 ++n_;
141 }
142 91 }
143
144 673 T* data() noexcept
145 {
146 return reinterpret_cast<
147 673 T*>(this + 1);
148 }
149 };
150
151 91 undo u(*this);
152 91 auto prev_head = head_;
153 182 head_ = bump_down(
154
1/1
✓ Branch 1 taken 91 times.
91 sizeof(U) + n * sizeof(T),
155 alignof(::max_align_t));
156 91 auto p = ::new(head_) U(n, t);
157 91 u.commit();
158 91 p->next = reinterpret_cast<
159 any*>(prev_head);
160 182 return p->data();
161 91 }
162
163 #if defined(BOOST_MSVC)
164 #pragma warning(pop) /* C4324 */
165 #endif
166
167 } // detail
168 } // http
169 } // boost
170
171 #endif
172