2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PAUSATION_HPP
11 #define BOOST_BEAST_WEBSOCKET_DETAIL_PAUSATION_HPP
13 #include <boost/beast/core/handler_ptr.hpp>
14 #include <boost/asio/associated_allocator.hpp>
15 #include <boost/asio/coroutine.hpp>
16 #include <boost/assert.hpp>
27 // A container that holds a suspended, asynchronous composed
28 // operation. The contained object may be invoked later to
29 // resume the operation, or the container may be destroyed.
36 base(base &&) = delete;
37 base(base const&) = delete;
38 virtual ~base() = default;
39 virtual void operator()() = 0;
47 holder(holder&&) = default;
52 : f(std::forward<U>(u))
61 // invocation of f_() can
62 // assign a new object to *this.
67 struct exemplar : boost::asio::coroutine
76 using handler_type = H;
94 Op op(std::move(*op_));
96 typename std::allocator_traits<
97 boost::asio::associated_allocator_t<Op>>::
98 template rebind_alloc<Op> alloc{
99 boost::asio::get_associated_allocator(op)};
100 std::allocator_traits<
101 decltype(alloc)>::deallocate(alloc, op_, 1);
105 saved_op(saved_op&& other)
111 saved_op& operator=(saved_op&& other)
122 typename std::allocator_traits<
123 boost::asio::associated_allocator_t<Op>>::
124 template rebind_alloc<Op> alloc{
125 boost::asio::get_associated_allocator(op)};
126 auto const p = std::allocator_traits<
127 decltype(alloc)>::allocate(alloc, 1);
128 op_ = new(p) Op{std::move(op)};
135 Op op{std::move(*op_)};
136 typename std::allocator_traits<
137 boost::asio::associated_allocator_t<Op>>::
138 template rebind_alloc<Op> alloc{
139 boost::asio::get_associated_allocator(op)};
140 std::allocator_traits<
141 decltype(alloc)>::deallocate(alloc, op_, 1);
147 using buf_type = char[sizeof(holder<exemplar>)];
149 base* base_ = nullptr;
150 alignas(holder<exemplar>) buf_type buf_;
153 pausation() = default;
154 pausation(pausation const&) = delete;
155 pausation& operator=(pausation const&) = delete;
163 pausation(pausation&& other)
165 boost::ignore_unused(other);
166 BOOST_ASSERT(! other.base_);
170 operator=(pausation&& other)
172 boost::ignore_unused(other);
173 BOOST_ASSERT(! base_);
174 BOOST_ASSERT(! other.base_);
187 operator bool() const
189 return base_ != nullptr;
197 auto const basep = base_;
208 pausation::emplace(F&& f)
210 using type = holder<typename std::decay<F>::type>;
211 static_assert(sizeof(buf_type) >= sizeof(type),
213 BOOST_ASSERT(! base_);
214 base_ = ::new(buf_) type{std::forward<F>(f)};
219 pausation::save(F&& f)
221 emplace(saved_op<F>{std::move(f)});