ゴミ箱
pausation.hpp
Go to the documentation of this file.
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 
14 #include <boost/asio/coroutine.hpp>
15 #include <boost/assert.hpp>
16 #include <array>
17 #include <memory>
18 #include <new>
19 #include <utility>
20 
21 namespace boost {
22 namespace beast {
23 namespace websocket {
24 namespace detail {
25 
26 // A container that holds a suspended, asynchronous composed
27 // operation. The contained object may be invoked later to
28 // resume the operation, or the container may be destroyed.
29 //
30 class pausation
31 {
32  struct base
33  {
34  base() = default;
35  base(base &&) = delete;
36  base(base const&) = delete;
37  virtual ~base() = default;
38  virtual void operator()() = 0;
39  };
40 
41  template<class F>
42  struct holder : base
43  {
44  F f;
45 
46  holder(holder&&) = default;
47 
48  template<class U>
49  explicit
50  holder(U&& u)
51  : f(std::forward<U>(u))
52  {
53  }
54 
55  void
56  operator()() override
57  {
58  F f_(std::move(f));
59  this->~holder();
60  // invocation of f_() can
61  // assign a new object to *this.
62  f_();
63  }
64  };
65 
66  struct exemplar : boost::asio::coroutine
67  {
68  struct H
69  {
70  void operator()();
71  };
72 
73  struct T
74  {
75  using handler_type = H;
76  };
77 
79 
80  void operator()();
81  };
82 
83  template<class Op>
84  class saved_op
85  {
86  Op* op_ = nullptr;
87 
88  public:
89  ~saved_op()
90  {
91  using boost::asio::asio_handler_deallocate;
92  if(op_)
93  {
94  Op op(std::move(*op_));
95  op_->~Op();
96  asio_handler_deallocate(op_,
97  sizeof(*op_), std::addressof(op.handler()));
98  }
99  }
100 
101  saved_op(saved_op&& other)
102  : op_(other.op_)
103  {
104  other.op_ = nullptr;
105  }
106 
107  saved_op& operator=(saved_op&& other)
108  {
109  BOOST_ASSERT(! op_);
110  op_ = other.op_;
111  other.op_ = 0;
112  return *this;
113  }
114 
115  explicit
116  saved_op(Op&& op)
117  {
118  using boost::asio::asio_handler_allocate;
119  op_ = new(asio_handler_allocate(sizeof(Op),
120  std::addressof(op.handler()))) Op{
121  std::move(op)};
122  }
123 
124  void
125  operator()()
126  {
127  BOOST_ASSERT(op_);
128  Op op{std::move(*op_)};
129  using boost::asio::asio_handler_deallocate;
130  asio_handler_deallocate(op_,
131  sizeof(*op_), std::addressof(op_->handler()));
132  op_ = nullptr;
133  op();
134  }
135  };
136 
137  using buf_type = char[sizeof(holder<exemplar>)];
138 
139  base* base_ = nullptr;
140  alignas(holder<exemplar>) buf_type buf_;
141 
142 public:
143  pausation() = default;
144  pausation(pausation const&) = delete;
145  pausation& operator=(pausation const&) = delete;
146 
148  {
149  if(base_)
150  base_->~base();
151  }
152 
154  {
155  BOOST_ASSERT(! other.base_);
156  }
157 
158  pausation&
160  {
161  BOOST_ASSERT(! base_);
162  BOOST_ASSERT(! other.base_);
163  return *this;
164  }
165 
166  template<class F>
167  void
168  emplace(F&& f);
169 
170  template<class F>
171  void
172  save(F&& f);
173 
174  explicit
175  operator bool() const
176  {
177  return base_ != nullptr;
178  }
179 
180  bool
182  {
183  if(base_)
184  {
185  auto const basep = base_;
186  base_ = nullptr;
187  (*basep)();
188  return true;
189  }
190  return false;
191  }
192 };
193 
194 template<class F>
195 void
197 {
198  using type = holder<typename std::decay<F>::type>;
199  static_assert(sizeof(buf_type) >= sizeof(type),
200  "buffer too small");
201  BOOST_ASSERT(! base_);
202  base_ = ::new(buf_) type{std::forward<F>(f)};
203 }
204 
205 template<class F>
206 void
208 {
209  emplace(saved_op<F>{std::move(f)});
210 }
211 
212 } // detail
213 } // websocket
214 } // beast
215 } // boost
216 
217 #endif
~pausation()
Definition: pausation.hpp:147
void save(F &&f)
Definition: pausation.hpp:207
bool maybe_invoke()
Definition: pausation.hpp:181
Definition: async_result.hpp:20
Definition: handler_ptr.hpp:53
pausation & operator=(pausation &&other)
Definition: pausation.hpp:159
pausation & operator=(pausation const &)=delete
Definition: pausation.hpp:30
void emplace(F &&f)
Definition: pausation.hpp:196
pausation(pausation &&other)
Definition: pausation.hpp:153