97.14% Lines (34/35) 100.00% Functions (8/8)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/http 7   // Official repository: https://github.com/cppalliance/http
8   // 8   //
9   9  
10   #ifndef BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP 10   #ifndef BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP
11   #define BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP 11   #define BOOST_HTTP_DETAIL_IMPL_WORKSPACE_HPP
12   12  
13   #include <boost/config.hpp> 13   #include <boost/config.hpp>
14   14  
15   namespace boost { 15   namespace boost {
16   namespace http { 16   namespace http {
17   namespace detail { 17   namespace detail {
18   18  
19   #if defined(BOOST_MSVC) 19   #if defined(BOOST_MSVC)
20   #pragma warning(push) 20   #pragma warning(push)
21   #pragma warning(disable : 4324) /* structure was padded due to __declspec(align()) */ 21   #pragma warning(disable : 4324) /* structure was padded due to __declspec(align()) */
22   #endif 22   #endif
23   23  
24   struct workspace::any 24   struct workspace::any
25   { 25   {
26   any* next = nullptr; 26   any* next = nullptr;
27   27  
28   BOOST_HTTP_DECL 28   BOOST_HTTP_DECL
29   virtual ~any() = 0; 29   virtual ~any() = 0;
30   }; 30   };
31   31  
32   template<class U> 32   template<class U>
33   struct alignas(::max_align_t) 33   struct alignas(::max_align_t)
34   workspace::any_impl : any 34   workspace::any_impl : any
35   { 35   {
36   U u; 36   U u;
37   37  
38   any_impl(any_impl const&) = delete; 38   any_impl(any_impl const&) = delete;
39   any_impl(any_impl&&) = delete; 39   any_impl(any_impl&&) = delete;
40   40  
41   template<class... Args> 41   template<class... Args>
42   explicit any_impl(Args&&... args) 42   explicit any_impl(Args&&... args)
43   : u(std::forward<Args>(args)...) 43   : u(std::forward<Args>(args)...)
44   { 44   {
45   } 45   }
46   }; 46   };
47   47  
48   struct workspace::undo 48   struct workspace::undo
49   { 49   {
50   explicit 50   explicit
HITCBC 51   159 undo(workspace& ws0) noexcept 51   159 undo(workspace& ws0) noexcept
HITCBC 52   159 : ws_(ws0) 52   159 : ws_(ws0)
HITCBC 53   159 , head_(ws0.head_) 53   159 , head_(ws0.head_)
54   { 54   {
HITCBC 55   159 } 55   159 }
56   56  
HITCBC 57   159 ~undo() 57   159 ~undo()
58   { 58   {
HITCBC 59   159 if(head_) 59   159 if(head_)
MISUBC 60   ws_.head_ = head_; 60   ws_.head_ = head_;
HITCBC 61   159 } 61   159 }
62   62  
63   void 63   void
HITCBC 64   159 commit() noexcept 64   159 commit() noexcept
65   { 65   {
HITCBC 66   159 head_ = nullptr; 66   159 head_ = nullptr;
HITCBC 67   159 } 67   159 }
68   68  
69   private: 69   private:
70   workspace& ws_; 70   workspace& ws_;
71   unsigned char* head_; 71   unsigned char* head_;
72   }; 72   };
73   73  
74   template<class T> 74   template<class T>
75   constexpr 75   constexpr
76   std::size_t 76   std::size_t
77   workspace:: 77   workspace::
78   space_needed() 78   space_needed()
79   { 79   {
80   using U = typename std::decay<T>::type; 80   using U = typename std::decay<T>::type;
81   81  
82   static_assert( 82   static_assert(
83   alignof(U) <= alignof(::max_align_t), 83   alignof(U) <= alignof(::max_align_t),
84   "Overaligned types not supported"); 84   "Overaligned types not supported");
85   85  
86   return sizeof(any_impl<U>); 86   return sizeof(any_impl<U>);
87   } 87   }
88   88  
89   template<class T, class... Args> 89   template<class T, class... Args>
90   auto 90   auto
91   workspace:: 91   workspace::
92   emplace(Args&&... args) -> 92   emplace(Args&&... args) ->
93   typename std::decay<T>::type& 93   typename std::decay<T>::type&
94   { 94   {
95   static_assert( 95   static_assert(
96   alignof(T) <= alignof(::max_align_t), 96   alignof(T) <= alignof(::max_align_t),
97   "Overaligned types not supported"); 97   "Overaligned types not supported");
98   98  
99   using U = any_impl<typename 99   using U = any_impl<typename
100   std::decay<T>::type>; 100   std::decay<T>::type>;
101   101  
102   undo u(*this); 102   undo u(*this);
103   auto prev_head = head_; 103   auto prev_head = head_;
104   head_ = bump_down(sizeof(U), alignof(U)); 104   head_ = bump_down(sizeof(U), alignof(U));
105   auto p = ::new(head_) U( 105   auto p = ::new(head_) U(
106   std::forward<Args>(args)...); 106   std::forward<Args>(args)...);
107   u.commit(); 107   u.commit();
108   p->next = reinterpret_cast< 108   p->next = reinterpret_cast<
109   any*>(prev_head); 109   any*>(prev_head);
110   return p->u; 110   return p->u;
111   } 111   }
112   112  
113   template<class T> 113   template<class T>
114   T* 114   T*
HITCBC 115   159 workspace:: 115   159 workspace::
116   push_array( 116   push_array(
117   std::size_t n, 117   std::size_t n,
118   T const& t) 118   T const& t)
119   { 119   {
120   struct alignas(::max_align_t) 120   struct alignas(::max_align_t)
121   U : any 121   U : any
122   { 122   {
123   std::size_t n_ = 0; 123   std::size_t n_ = 0;
124   124  
HITCBC 125   159 U() = default; 125   159 U() = default;
HITCBC 126   159 ~U() 126   159 ~U()
127   { 127   {
HITCBC 128   159 for(std::size_t i = n_; 128   159 for(std::size_t i = n_;
HITCBC 129   636 i-- > 0;) 129   636 i-- > 0;)
HITCBC 130   477 data()[i].~T(); 130   477 data()[i].~T();
HITCBC 131   318 } 131   318 }
132   132  
HITCBC 133   159 U( std::size_t n, 133   159 U( std::size_t n,
134   T const& t) 134   T const& t)
HITCBC 135   159 : U() 135   159 : U()
136   { 136   {
HITCBC 137   636 while(n_ < n) 137   636 while(n_ < n)
138   { 138   {
HITCBC 139   477 new(&data()[n_]) T(t); 139   477 new(&data()[n_]) T(t);
HITCBC 140   477 ++n_; 140   477 ++n_;
141   } 141   }
HITCBC 142   159 } 142   159 }
143   143  
HITCBC 144   1113 T* data() noexcept 144   1113 T* data() noexcept
145   { 145   {
146   return reinterpret_cast< 146   return reinterpret_cast<
HITCBC 147   1113 T*>(this + 1); 147   1113 T*>(this + 1);
148   } 148   }
149   }; 149   };
150   150  
HITCBC 151   159 undo u(*this); 151   159 undo u(*this);
HITCBC 152   159 auto prev_head = head_; 152   159 auto prev_head = head_;
HITCBC 153   318 head_ = bump_down( 153   318 head_ = bump_down(
HITCBC 154   159 sizeof(U) + n * sizeof(T), 154   159 sizeof(U) + n * sizeof(T),
155   alignof(::max_align_t)); 155   alignof(::max_align_t));
HITCBC 156   159 auto p = ::new(head_) U(n, t); 156   159 auto p = ::new(head_) U(n, t);
HITCBC 157   159 u.commit(); 157   159 u.commit();
HITCBC 158   159 p->next = reinterpret_cast< 158   159 p->next = reinterpret_cast<
159   any*>(prev_head); 159   any*>(prev_head);
HITCBC 160   318 return p->data(); 160   318 return p->data();
HITCBC 161   159 } 161   159 }
162   162  
163   #if defined(BOOST_MSVC) 163   #if defined(BOOST_MSVC)
164   #pragma warning(pop) /* C4324 */ 164   #pragma warning(pop) /* C4324 */
165   #endif 165   #endif
166   166  
167   } // detail 167   } // detail
168   } // http 168   } // http
169   } // boost 169   } // boost
170   170  
171   #endif 171   #endif