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
51  
    undo(workspace& ws0) noexcept
51  
    undo(workspace& ws0) noexcept
52  
        : ws_(ws0)
52  
        : ws_(ws0)
53  
        , head_(ws0.head_)
53  
        , head_(ws0.head_)
54  
    {
54  
    {
55  
    }
55  
    }
56  

56  

57  
    ~undo()
57  
    ~undo()
58  
    {
58  
    {
59  
        if(head_)
59  
        if(head_)
60  
            ws_.head_ = head_;
60  
            ws_.head_ = head_;
61  
    }
61  
    }
62  

62  

63  
    void
63  
    void
64  
    commit() noexcept
64  
    commit() noexcept
65  
    {
65  
    {
66  
        head_ = nullptr;
66  
        head_ = nullptr;
67  
    }
67  
    }
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*
115  
workspace::
115  
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  

125  
        U() = default;
125  
        U() = default;
126  
        ~U()
126  
        ~U()
127  
        {
127  
        {
128  
            for(std::size_t i = n_;
128  
            for(std::size_t i = n_;
129  
                    i-- > 0;)
129  
                    i-- > 0;)
130  
                data()[i].~T();
130  
                data()[i].~T();
131  
        }
131  
        }
132  

132  

133  
        U(  std::size_t n,
133  
        U(  std::size_t n,
134  
            T const& t)
134  
            T const& t)
135  
            : U()
135  
            : U()
136  
        {
136  
        {
137  
            while(n_ < n)
137  
            while(n_ < n)
138  
            {
138  
            {
139  
                new(&data()[n_]) T(t);
139  
                new(&data()[n_]) T(t);
140  
                ++n_;
140  
                ++n_;
141  
            }
141  
            }
142  
        }
142  
        }
143  

143  

144  
        T* data() noexcept
144  
        T* data() noexcept
145  
        {
145  
        {
146  
            return reinterpret_cast<
146  
            return reinterpret_cast<
147  
                T*>(this + 1);
147  
                T*>(this + 1);
148  
        }
148  
        }
149  
    };
149  
    };
150  

150  

151  
    undo u(*this);
151  
    undo u(*this);
152  
    auto prev_head = head_;
152  
    auto prev_head = head_;
153  
    head_ = bump_down(
153  
    head_ = bump_down(
154  
        sizeof(U) + n * sizeof(T),
154  
        sizeof(U) + n * sizeof(T),
155  
        alignof(::max_align_t));
155  
        alignof(::max_align_t));
156  
    auto p = ::new(head_) U(n, t);
156  
    auto p = ::new(head_) U(n, t);
157  
    u.commit();
157  
    u.commit();
158  
    p->next = reinterpret_cast<
158  
    p->next = reinterpret_cast<
159  
        any*>(prev_head);
159  
        any*>(prev_head);
160  
    return p->data();
160  
    return p->data();
161  
}
161  
}
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