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