]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-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 | ||
8 | #ifndef BEAST_IMPL_HANDLER_PTR_HPP | |
9 | #define BEAST_IMPL_HANDLER_PTR_HPP | |
10 | ||
11 | #include <beast/core/handler_helpers.hpp> | |
12 | #include <boost/asio/detail/handler_alloc_helpers.hpp> | |
13 | #include <boost/assert.hpp> | |
14 | #include <memory> | |
15 | ||
16 | namespace beast { | |
17 | ||
18 | template<class T, class Handler> | |
19 | template<class DeducedHandler, class... Args> | |
20 | inline | |
21 | handler_ptr<T, Handler>::P:: | |
22 | P(DeducedHandler&& h, Args&&... args) | |
23 | : n(1) | |
24 | , handler(std::forward<DeducedHandler>(h)) | |
25 | { | |
26 | t = reinterpret_cast<T*>( | |
27 | beast_asio_helpers:: | |
28 | allocate(sizeof(T), handler)); | |
29 | try | |
30 | { | |
31 | t = new(t) T{handler, | |
32 | std::forward<Args>(args)...}; | |
33 | } | |
34 | catch(...) | |
35 | { | |
36 | beast_asio_helpers:: | |
37 | deallocate(t, sizeof(T), handler); | |
38 | throw; | |
39 | } | |
40 | } | |
41 | ||
42 | template<class T, class Handler> | |
43 | handler_ptr<T, Handler>:: | |
44 | ~handler_ptr() | |
45 | { | |
46 | if(! p_) | |
47 | return; | |
48 | if(--p_->n) | |
49 | return; | |
50 | if(p_->t) | |
51 | { | |
52 | p_->t->~T(); | |
53 | beast_asio_helpers:: | |
54 | deallocate(p_->t, sizeof(T), p_->handler); | |
55 | } | |
56 | delete p_; | |
57 | } | |
58 | ||
59 | template<class T, class Handler> | |
60 | handler_ptr<T, Handler>:: | |
61 | handler_ptr(handler_ptr&& other) | |
62 | : p_(other.p_) | |
63 | { | |
64 | other.p_ = nullptr; | |
65 | } | |
66 | ||
67 | template<class T, class Handler> | |
68 | handler_ptr<T, Handler>:: | |
69 | handler_ptr(handler_ptr const& other) | |
70 | : p_(other.p_) | |
71 | { | |
72 | if(p_) | |
73 | ++p_->n; | |
74 | } | |
75 | ||
76 | template<class T, class Handler> | |
77 | template<class... Args> | |
78 | handler_ptr<T, Handler>:: | |
79 | handler_ptr(Handler&& handler, Args&&... args) | |
80 | : p_(new P{std::move(handler), | |
81 | std::forward<Args>(args)...}) | |
82 | { | |
83 | static_assert(! std::is_array<T>::value, | |
84 | "T must not be an array type"); | |
85 | } | |
86 | ||
87 | template<class T, class Handler> | |
88 | template<class... Args> | |
89 | handler_ptr<T, Handler>:: | |
90 | handler_ptr(Handler const& handler, Args&&... args) | |
91 | : p_(new P{handler, std::forward<Args>(args)...}) | |
92 | { | |
93 | static_assert(! std::is_array<T>::value, | |
94 | "T must not be an array type"); | |
95 | } | |
96 | ||
97 | template<class T, class Handler> | |
98 | auto | |
99 | handler_ptr<T, Handler>:: | |
100 | release_handler() -> | |
101 | handler_type | |
102 | { | |
103 | BOOST_ASSERT(p_); | |
104 | BOOST_ASSERT(p_->t); | |
105 | p_->t->~T(); | |
106 | beast_asio_helpers:: | |
107 | deallocate(p_->t, sizeof(T), p_->handler); | |
108 | p_->t = nullptr; | |
109 | return std::move(p_->handler); | |
110 | } | |
111 | ||
112 | template<class T, class Handler> | |
113 | template<class... Args> | |
114 | void | |
115 | handler_ptr<T, Handler>:: | |
116 | invoke(Args&&... args) | |
117 | { | |
118 | BOOST_ASSERT(p_); | |
119 | BOOST_ASSERT(p_->t); | |
120 | p_->t->~T(); | |
121 | beast_asio_helpers:: | |
122 | deallocate(p_->t, sizeof(T), p_->handler); | |
123 | p_->t = nullptr; | |
124 | p_->handler(std::forward<Args>(args)...); | |
125 | } | |
126 | ||
127 | } // beast | |
128 | ||
129 | #endif |