1 | // Copyright (C) 2013 Vicente J. Botet Escriba |
---|---|
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | // |
6 | // 2013/09 Vicente J. Botet Escriba |
7 | // Adapt to boost from CCIA C++11 implementation |
8 | // Make use of Boost.Move |
9 | |
10 | #ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP |
11 | #define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP |
12 | |
13 | #include <boost/config.hpp> |
14 | #include <boost/thread/detail/memory.hpp> |
15 | #include <boost/thread/detail/move.hpp> |
16 | #include <boost/thread/csbl/memory/shared_ptr.hpp> |
17 | #include <boost/type_traits/decay.hpp> |
18 | |
19 | namespace boost |
20 | { |
21 | namespace detail |
22 | { |
23 | |
24 | template <typename F> |
25 | class nullary_function; |
26 | template <> |
27 | class nullary_function<void()> |
28 | { |
29 | struct impl_base |
30 | { |
31 | virtual void call()=0; |
32 | virtual ~impl_base() |
33 | { |
34 | } |
35 | }; |
36 | csbl::shared_ptr<impl_base> impl; |
37 | template <typename F> |
38 | struct impl_type: impl_base |
39 | { |
40 | F f; |
41 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
42 | impl_type(F &f_) |
43 | : f(f_) |
44 | {} |
45 | #endif |
46 | impl_type(BOOST_THREAD_RV_REF(F) f_) |
47 | : f(boost::move(f_)) |
48 | {} |
49 | |
50 | void call() |
51 | { |
52 | f(); |
53 | } |
54 | }; |
55 | struct impl_type_ptr: impl_base |
56 | { |
57 | void (*f)(); |
58 | impl_type_ptr(void (*f_)()) |
59 | : f(f_) |
60 | {} |
61 | void call() |
62 | { |
63 | f(); |
64 | } |
65 | }; |
66 | public: |
67 | BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function) |
68 | |
69 | explicit nullary_function(void (*f)()): |
70 | impl(new impl_type_ptr(f)) |
71 | {} |
72 | |
73 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
74 | template<typename F> |
75 | explicit nullary_function(F& f): |
76 | impl(new impl_type<F>(f)) |
77 | {} |
78 | #endif |
79 | template<typename F> |
80 | nullary_function(BOOST_THREAD_RV_REF(F) f): |
81 | impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f)))) |
82 | {} |
83 | |
84 | nullary_function() |
85 | : impl() |
86 | { |
87 | } |
88 | nullary_function(nullary_function const& other) BOOST_NOEXCEPT : |
89 | impl(other.impl) |
90 | { |
91 | } |
92 | nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : |
93 | #if defined BOOST_NO_CXX11_SMART_PTR |
94 | impl(BOOST_THREAD_RV(other).impl) |
95 | { |
96 | BOOST_THREAD_RV(other).impl.reset(); |
97 | } |
98 | #else |
99 | impl(boost::move(other.impl)) |
100 | { |
101 | } |
102 | #endif |
103 | ~nullary_function() |
104 | { |
105 | } |
106 | |
107 | nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT |
108 | { |
109 | impl=other.impl; |
110 | return *this; |
111 | } |
112 | nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT |
113 | { |
114 | #if defined BOOST_NO_CXX11_SMART_PTR |
115 | impl=BOOST_THREAD_RV(other).impl; |
116 | BOOST_THREAD_RV(other).impl.reset(); |
117 | #else |
118 | impl = boost::move(other.impl); |
119 | #endif |
120 | return *this; |
121 | } |
122 | |
123 | |
124 | void operator()() |
125 | { if (impl) impl->call();} |
126 | |
127 | }; |
128 | |
129 | template <typename R> |
130 | class nullary_function<R()> |
131 | { |
132 | struct impl_base |
133 | { |
134 | virtual R call()=0; |
135 | virtual ~impl_base() |
136 | { |
137 | } |
138 | }; |
139 | csbl::shared_ptr<impl_base> impl; |
140 | template <typename F> |
141 | struct impl_type: impl_base |
142 | { |
143 | F f; |
144 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
145 | impl_type(F &f_) |
146 | : f(f_) |
147 | {} |
148 | #endif |
149 | impl_type(BOOST_THREAD_RV_REF(F) f_) |
150 | : f(boost::move(f_)) |
151 | {} |
152 | |
153 | R call() |
154 | { |
155 | return f(); |
156 | } |
157 | }; |
158 | struct impl_type_ptr: impl_base |
159 | { |
160 | R (*f)(); |
161 | impl_type_ptr(R (*f_)()) |
162 | : f(f_) |
163 | {} |
164 | |
165 | R call() |
166 | { |
167 | return f(); |
168 | } |
169 | }; |
170 | public: |
171 | BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function) |
172 | |
173 | nullary_function(R (*f)()): |
174 | impl(new impl_type_ptr(f)) |
175 | {} |
176 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
177 | template<typename F> |
178 | nullary_function(F& f): |
179 | impl(new impl_type<F>(f)) |
180 | {} |
181 | #endif |
182 | template<typename F> |
183 | nullary_function(BOOST_THREAD_RV_REF(F) f): |
184 | impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f)))) |
185 | {} |
186 | |
187 | nullary_function(nullary_function const& other) BOOST_NOEXCEPT : |
188 | impl(other.impl) |
189 | { |
190 | } |
191 | nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : |
192 | #if defined BOOST_NO_CXX11_SMART_PTR |
193 | impl(BOOST_THREAD_RV(other).impl) |
194 | { |
195 | BOOST_THREAD_RV(other).impl.reset(); |
196 | } |
197 | #else |
198 | impl(boost::move(other.impl)) |
199 | { |
200 | } |
201 | #endif |
202 | nullary_function() |
203 | : impl() |
204 | { |
205 | } |
206 | ~nullary_function() |
207 | { |
208 | } |
209 | |
210 | nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT |
211 | { |
212 | impl=other.impl; |
213 | return *this; |
214 | } |
215 | nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT |
216 | { |
217 | #if defined BOOST_NO_CXX11_SMART_PTR |
218 | impl=BOOST_THREAD_RV(other).impl; |
219 | BOOST_THREAD_RV(other).impl.reset(); |
220 | #else |
221 | impl = boost::move(other.impl); |
222 | #endif |
223 | return *this; |
224 | } |
225 | |
226 | R operator()() |
227 | { if (impl) return impl->call(); else return R();} |
228 | |
229 | }; |
230 | } |
231 | BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END |
232 | } |
233 | |
234 | #endif // header |
235 |