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;
~impl_baseboost::detail::nullary_function::impl_base32         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
impl_typeboost::detail::nullary_function::impl_type42         impl_type(F &f_)
43           : f(f_)
44         {}
45 #endif
impl_typeboost::detail::nullary_function::impl_type46         impl_type(BOOST_THREAD_RV_REF(F) f_)
47           : f(boost::move(f_))
48         {}
49 
callboost::detail::nullary_function::impl_type50         void call()
51         {
52           f();
53         }
54       };
55       struct impl_type_ptr: impl_base
56       {
57         void (*f)();
impl_type_ptrboost::detail::nullary_function::impl_type_ptr58         impl_type_ptr(void (*f_)())
59           : f(f_)
60         {}
callboost::detail::nullary_function::impl_type_ptr61         void call()
62         {
63           f();
64         }
65       };
66     public:
67       BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
68 
nullary_function(void (* f)())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>
nullary_function(F & f)75       explicit nullary_function(F& f):
76       impl(new impl_type<F>(f))
77       {}
78 #endif
79       template<typename F>
nullary_function(BOOST_THREAD_RV_REF (F)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 
nullary_function()84       nullary_function()
85         : impl()
86       {
87       }
nullary_function(nullary_function const & other)88       nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
89       impl(other.impl)
90       {
91       }
nullary_function(BOOST_THREAD_RV_REF (nullary_function)other)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
~nullary_function()103       ~nullary_function()
104       {
105       }
106 
operator =(BOOST_THREAD_COPY_ASSIGN_REF (nullary_function)other)107       nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
108       {
109         impl=other.impl;
110         return *this;
111       }
operator =(BOOST_THREAD_RV_REF (nullary_function)other)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 
operator ()()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;
~impl_baseboost::detail::nullary_function::impl_base135         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
impl_typeboost::detail::nullary_function::impl_type145         impl_type(F &f_)
146           : f(f_)
147         {}
148 #endif
impl_typeboost::detail::nullary_function::impl_type149         impl_type(BOOST_THREAD_RV_REF(F) f_)
150           : f(boost::move(f_))
151         {}
152 
callboost::detail::nullary_function::impl_type153         R call()
154         {
155           return f();
156         }
157       };
158       struct impl_type_ptr: impl_base
159       {
160         R (*f)();
impl_type_ptrboost::detail::nullary_function::impl_type_ptr161         impl_type_ptr(R (*f_)())
162           : f(f_)
163         {}
164 
callboost::detail::nullary_function::impl_type_ptr165         R call()
166         {
167           return f();
168         }
169       };
170     public:
171       BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
172 
nullary_function(R (* f)())173       nullary_function(R (*f)()):
174       impl(new impl_type_ptr(f))
175       {}
176 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
177       template<typename F>
nullary_function(F & f)178       nullary_function(F& f):
179       impl(new impl_type<F>(f))
180       {}
181 #endif
182       template<typename F>
nullary_function(BOOST_THREAD_RV_REF (F)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 
nullary_function(nullary_function const & other)187       nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
188       impl(other.impl)
189       {
190       }
nullary_function(BOOST_THREAD_RV_REF (nullary_function)other)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
nullary_function()202       nullary_function()
203         : impl()
204       {
205       }
~nullary_function()206       ~nullary_function()
207       {
208       }
209 
operator =(BOOST_THREAD_COPY_ASSIGN_REF (nullary_function)other)210       nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
211       {
212         impl=other.impl;
213         return *this;
214       }
operator =(BOOST_THREAD_RV_REF (nullary_function)other)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 
operator ()()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