]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot 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/boostorg/beast | |
8 | // | |
9 | ||
10 | #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PAUSATION_HPP | |
11 | #define BOOST_BEAST_WEBSOCKET_DETAIL_PAUSATION_HPP | |
12 | ||
11fdf7f2 | 13 | #include <boost/beast/core/detail/allocator.hpp> |
b32b8144 | 14 | #include <boost/asio/associated_allocator.hpp> |
b32b8144 | 15 | #include <boost/assert.hpp> |
b32b8144 | 16 | #include <memory> |
b32b8144 FG |
17 | #include <utility> |
18 | ||
19 | namespace boost { | |
20 | namespace beast { | |
21 | namespace websocket { | |
22 | namespace detail { | |
23 | ||
24 | // A container that holds a suspended, asynchronous composed | |
25 | // operation. The contained object may be invoked later to | |
26 | // resume the operation, or the container may be destroyed. | |
27 | // | |
28 | class pausation | |
29 | { | |
11fdf7f2 | 30 | struct handler |
b32b8144 | 31 | { |
11fdf7f2 TL |
32 | handler() = default; |
33 | handler(handler &&) = delete; | |
34 | handler(handler const&) = delete; | |
35 | virtual ~handler() = default; | |
36 | virtual void destroy() = 0; | |
37 | virtual void invoke() = 0; | |
b32b8144 FG |
38 | }; |
39 | ||
11fdf7f2 TL |
40 | template<class Handler> |
41 | class impl : public handler | |
b32b8144 | 42 | { |
11fdf7f2 | 43 | Handler h_; |
b32b8144 FG |
44 | |
45 | public: | |
11fdf7f2 TL |
46 | template<class DeducedHandler> |
47 | impl(DeducedHandler&& h) | |
48 | : h_(std::forward<DeducedHandler>(h)) | |
b32b8144 | 49 | { |
b32b8144 FG |
50 | } |
51 | ||
11fdf7f2 TL |
52 | void |
53 | destroy() override | |
b32b8144 | 54 | { |
11fdf7f2 TL |
55 | Handler h(std::move(h_)); |
56 | typename beast::detail::allocator_traits< | |
57 | boost::asio::associated_allocator_t< | |
58 | Handler>>::template rebind_alloc<impl> alloc{ | |
59 | boost::asio::get_associated_allocator(h)}; | |
60 | beast::detail::allocator_traits< | |
61 | decltype(alloc)>::destroy(alloc, this); | |
62 | beast::detail::allocator_traits< | |
63 | decltype(alloc)>::deallocate(alloc, this, 1); | |
b32b8144 FG |
64 | } |
65 | ||
66 | void | |
11fdf7f2 | 67 | invoke() override |
b32b8144 | 68 | { |
11fdf7f2 TL |
69 | Handler h(std::move(h_)); |
70 | typename beast::detail::allocator_traits< | |
71 | boost::asio::associated_allocator_t< | |
72 | Handler>>::template rebind_alloc<impl> alloc{ | |
73 | boost::asio::get_associated_allocator(h)}; | |
74 | beast::detail::allocator_traits< | |
75 | decltype(alloc)>::destroy(alloc, this); | |
76 | beast::detail::allocator_traits< | |
77 | decltype(alloc)>::deallocate(alloc, this, 1); | |
78 | h(); | |
b32b8144 FG |
79 | } |
80 | }; | |
81 | ||
11fdf7f2 | 82 | handler* h_ = nullptr; |
b32b8144 FG |
83 | |
84 | public: | |
85 | pausation() = default; | |
86 | pausation(pausation const&) = delete; | |
87 | pausation& operator=(pausation const&) = delete; | |
88 | ||
89 | ~pausation() | |
90 | { | |
11fdf7f2 TL |
91 | if(h_) |
92 | h_->destroy(); | |
b32b8144 FG |
93 | } |
94 | ||
95 | pausation(pausation&& other) | |
96 | { | |
97 | boost::ignore_unused(other); | |
11fdf7f2 | 98 | BOOST_ASSERT(! other.h_); |
b32b8144 FG |
99 | } |
100 | ||
101 | pausation& | |
102 | operator=(pausation&& other) | |
103 | { | |
104 | boost::ignore_unused(other); | |
11fdf7f2 TL |
105 | BOOST_ASSERT(! h_); |
106 | BOOST_ASSERT(! other.h_); | |
b32b8144 FG |
107 | return *this; |
108 | } | |
109 | ||
11fdf7f2 | 110 | template<class CompletionHandler> |
b32b8144 | 111 | void |
11fdf7f2 | 112 | emplace(CompletionHandler&& handler); |
b32b8144 FG |
113 | |
114 | explicit | |
115 | operator bool() const | |
116 | { | |
11fdf7f2 | 117 | return h_ != nullptr; |
b32b8144 FG |
118 | } |
119 | ||
120 | bool | |
121 | maybe_invoke() | |
122 | { | |
11fdf7f2 | 123 | if(h_) |
b32b8144 | 124 | { |
11fdf7f2 TL |
125 | auto const h = h_; |
126 | h_ = nullptr; | |
127 | h->invoke(); | |
b32b8144 FG |
128 | return true; |
129 | } | |
130 | return false; | |
131 | } | |
132 | }; | |
133 | ||
11fdf7f2 | 134 | template<class CompletionHandler> |
b32b8144 | 135 | void |
11fdf7f2 | 136 | pausation::emplace(CompletionHandler&& handler) |
b32b8144 | 137 | { |
11fdf7f2 TL |
138 | BOOST_ASSERT(! h_); |
139 | typename beast::detail::allocator_traits< | |
140 | boost::asio::associated_allocator_t< | |
141 | CompletionHandler>>::template rebind_alloc< | |
142 | impl<CompletionHandler>> alloc{ | |
143 | boost::asio::get_associated_allocator(handler)}; | |
144 | using A = decltype(alloc); | |
145 | auto const d = | |
146 | [&alloc](impl<CompletionHandler>* p) | |
147 | { | |
148 | beast::detail::allocator_traits<A>::deallocate(alloc, p, 1); | |
149 | }; | |
150 | std::unique_ptr<impl<CompletionHandler>, decltype(d)> p{ | |
151 | beast::detail::allocator_traits<A>::allocate(alloc, 1), d}; | |
152 | beast::detail::allocator_traits<A>::construct( | |
153 | alloc, p.get(), std::forward<CompletionHandler>(handler)); | |
154 | h_ = p.release(); | |
b32b8144 FG |
155 | } |
156 | ||
157 | } // detail | |
158 | } // websocket | |
159 | } // beast | |
160 | } // boost | |
161 | ||
162 | #endif |