Line | Branch | Exec | Source |
---|---|---|---|
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_WORKSPACE_HPP | ||
11 | #define BOOST_HTTP_PROTO_DETAIL_WORKSPACE_HPP | ||
12 | |||
13 | #include <boost/http_proto/detail/except.hpp> | ||
14 | #include <boost/assert.hpp> | ||
15 | #include <cstdlib> | ||
16 | #include <new> | ||
17 | #include <utility> | ||
18 | #include <stddef.h> // ::max_align_t | ||
19 | |||
20 | namespace boost { | ||
21 | namespace http_proto { | ||
22 | namespace detail { | ||
23 | |||
24 | class workspace | ||
25 | { | ||
26 | 74 | struct any | |
27 | { | ||
28 | any* next = nullptr; | ||
29 | |||
30 | BOOST_HTTP_PROTO_DECL | ||
31 | virtual ~any() = 0; | ||
32 | }; | ||
33 | |||
34 | unsigned char* begin_ = nullptr; | ||
35 | unsigned char* end_; | ||
36 | unsigned char* head_; | ||
37 | |||
38 | public: | ||
39 | ~workspace(); | ||
40 | |||
41 | 745 | workspace() = default; | |
42 | workspace(workspace&&) noexcept; | ||
43 | workspace& operator=( | ||
44 | workspace&&) noexcept; | ||
45 | |||
46 | explicit | ||
47 | workspace( | ||
48 | std::size_t n); | ||
49 | |||
50 | void* | ||
51 | 7952 | data() noexcept | |
52 | { | ||
53 | 7952 | return begin_; | |
54 | } | ||
55 | |||
56 | std::size_t | ||
57 | 14 | size() const noexcept | |
58 | { | ||
59 | 14 | return head_ - begin_; | |
60 | } | ||
61 | |||
62 | BOOST_HTTP_PROTO_DECL | ||
63 | void | ||
64 | clear() noexcept; | ||
65 | |||
66 | BOOST_HTTP_PROTO_DECL | ||
67 | void* | ||
68 | reserve(std::size_t n); | ||
69 | |||
70 | template<class T> | ||
71 | auto | ||
72 | push(T&& t) -> | ||
73 | typename std::decay<T>::type&; | ||
74 | |||
75 | template<class T> | ||
76 | T* | ||
77 | push_array( | ||
78 | std::size_t n, | ||
79 | T const& t); | ||
80 | |||
81 | private: | ||
82 | BOOST_HTTP_PROTO_DECL | ||
83 | void* | ||
84 | bump_down( | ||
85 | std::size_t size, | ||
86 | std::size_t align); | ||
87 | }; | ||
88 | |||
89 | template<class T> | ||
90 | auto | ||
91 | 26 | workspace:: | |
92 | push(T&& t) -> | ||
93 | typename std::decay<T>::type& | ||
94 | { | ||
95 | struct alignas(alignof(::max_align_t)) | ||
96 | U : any | ||
97 | { | ||
98 | typename std::decay<T>::type v_; | ||
99 | |||
100 | U() = delete; | ||
101 | U(U&&) = default; | ||
102 | |||
103 | 13 | explicit U(T&& t) | |
104 | 13 | : v_(std::move(t)) | |
105 | { | ||
106 | } | ||
107 | }; | ||
108 | |||
109 | 26 | auto p = ::new(bump_down( | |
110 | sizeof(U), alignof(U))) U( | ||
111 | 26 | std::forward<T>(t)); | |
112 | 26 | p->next = reinterpret_cast< | |
113 | 26 | any*>(head_); | |
114 | 26 | head_ = reinterpret_cast< | |
115 | unsigned char*>(p); | ||
116 | 26 | return p->v_; | |
117 | } | ||
118 | |||
119 | template<class T> | ||
120 | T* | ||
121 | 24 | workspace:: | |
122 | push_array( | ||
123 | std::size_t n, | ||
124 | T const& t) | ||
125 | { | ||
126 | struct alignas(alignof(::max_align_t)) | ||
127 | 24 | U : any | |
128 | { | ||
129 | std::size_t n_ = 0; | ||
130 | |||
131 | U() = default; | ||
132 | 48 | ~U() | |
133 | { | ||
134 | 140 | for(std::size_t i = n_; | |
135 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 24 times.
|
140 | i-- > 0;) |
136 | 92 | data()[i].~T(); | |
137 | } | ||
138 | |||
139 | 24 | U( std::size_t n, | |
140 | T const& t) | ||
141 | 24 | : U() | |
142 | { | ||
143 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 24 times.
|
70 | while(n_ < n) |
144 | { | ||
145 | 46 | new(&data()[n_]) T(t); | |
146 | 46 | ++n_; | |
147 | } | ||
148 | 24 | } | |
149 | |||
150 | 116 | T* data() noexcept | |
151 | { | ||
152 | return reinterpret_cast< | ||
153 | 116 | T*>(this + 1); | |
154 | } | ||
155 | }; | ||
156 | |||
157 | 24 | auto p = ::new(bump_down( | |
158 | 24 | sizeof(U) + n * sizeof(T), | |
159 | alignof(::max_align_t))) U(n, t); | ||
160 | 24 | p->next = reinterpret_cast< | |
161 | 24 | any*>(head_); | |
162 | 24 | head_ = reinterpret_cast< | |
163 | unsigned char*>(p); | ||
164 | 24 | return p->data(); | |
165 | } | ||
166 | |||
167 | } // detail | ||
168 | } // http_proto | ||
169 | } // boost | ||
170 | |||
171 | #endif | ||
172 |