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,2018 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 #include <boost/type_traits/is_same.hpp>
19 
20 namespace boost
21 {
22   namespace detail
23   {
24 
25     template <typename F>
26     class nullary_function;
27     template <>
28     class nullary_function<void()>
29     {
30       struct impl_base
31       {
32         virtual void call()=0;
~impl_baseboost::detail::nullary_function::impl_base33         virtual ~impl_base()
34         {
35         }
36       };
37       csbl::shared_ptr<impl_base> impl;
38       template <typename F>
39       struct impl_type: impl_base
40       {
41         F f;
42 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_typeboost::detail::nullary_function::impl_type43         impl_type(F &f_)
44           : f(f_)
45         {}
46 #endif
impl_typeboost::detail::nullary_function::impl_type47         impl_type(BOOST_THREAD_RV_REF(F) f_)
48           : f(boost::move(f_))
49         {}
50 
callboost::detail::nullary_function::impl_type51         void call()
52         {
53           f();
54         }
55       };
56       struct impl_type_ptr: impl_base
57       {
58         void (*f)();
impl_type_ptrboost::detail::nullary_function::impl_type_ptr59         impl_type_ptr(void (*f_)())
60           : f(f_)
61         {}
callboost::detail::nullary_function::impl_type_ptr62         void call()
63         {
64           f();
65         }
66       };
67     public:
68       BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
69 
nullary_function(void (* f)())70       explicit nullary_function(void (*f)()):
71       impl(new impl_type_ptr(f))
72       {}
73 
74 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
75       template<typename F>
nullary_function(F & f,typename disable_if<is_same<typename decay<F>::type,nullary_function>,int * >::type=0)76       explicit nullary_function(F& f
77                                 , typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
78                                 ):
79       impl(new impl_type<F>(f))
80       {}
81 #endif
82       template<typename F>
nullary_function(BOOST_THREAD_RV_REF (F)f,typename disable_if<is_same<typename decay<F>::type,nullary_function>,int * >::type=0)83       nullary_function(BOOST_THREAD_RV_REF(F) f
84                        , typename disable_if<is_same<typename decay<F>::type, nullary_function>, int* >::type=0
85                        ):
86       impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
87       {}
88 
nullary_function()89       nullary_function()
90         : impl()
91       {
92       }
nullary_function(nullary_function const & other)93       nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
94       impl(other.impl)
95       {
96       }
nullary_function(BOOST_THREAD_RV_REF (nullary_function)other)97       nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
98 #if defined BOOST_NO_CXX11_SMART_PTR
99       impl(BOOST_THREAD_RV(other).impl)
100       {
101         BOOST_THREAD_RV(other).impl.reset();
102       }
103 #else
104       impl(boost::move(other.impl))
105       {
106       }
107 #endif
~nullary_function()108       ~nullary_function()
109       {
110       }
111 
operator =(BOOST_THREAD_COPY_ASSIGN_REF (nullary_function)other)112       nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
113       {
114         impl=other.impl;
115         return *this;
116       }
operator =(BOOST_THREAD_RV_REF (nullary_function)other)117       nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
118       {
119 #if defined BOOST_NO_CXX11_SMART_PTR
120         impl=BOOST_THREAD_RV(other).impl;
121         BOOST_THREAD_RV(other).impl.reset();
122 #else
123         impl = boost::move(other.impl);
124 #endif
125         return *this;
126       }
127 
128 
operator ()()129       void operator()()
130       { if (impl) impl->call();}
131 
132     };
133 
134     template <typename R>
135     class nullary_function<R()>
136     {
137       struct impl_base
138       {
139         virtual R call()=0;
~impl_baseboost::detail::nullary_function::impl_base140         virtual ~impl_base()
141         {
142         }
143       };
144       csbl::shared_ptr<impl_base> impl;
145       template <typename F>
146       struct impl_type: impl_base
147       {
148         F f;
149 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
impl_typeboost::detail::nullary_function::impl_type150         impl_type(F &f_)
151           : f(f_)
152         {}
153 #endif
impl_typeboost::detail::nullary_function::impl_type154         impl_type(BOOST_THREAD_RV_REF(F) f_)
155           : f(boost::move(f_))
156         {}
157 
callboost::detail::nullary_function::impl_type158         R call()
159         {
160           return f();
161         }
162       };
163       struct impl_type_ptr: impl_base
164       {
165         R (*f)();
impl_type_ptrboost::detail::nullary_function::impl_type_ptr166         impl_type_ptr(R (*f_)())
167           : f(f_)
168         {}
169 
callboost::detail::nullary_function::impl_type_ptr170         R call()
171         {
172           return f();
173         }
174       };
175     public:
176       BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function)
177 
nullary_function(R (* f)())178       nullary_function(R (*f)()):
179       impl(new impl_type_ptr(f))
180       {}
181 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
182       template<typename F>
nullary_function(F & f)183       nullary_function(F& f):
184       impl(new impl_type<F>(f))
185       {}
186 #endif
187       template<typename F>
nullary_function(BOOST_THREAD_RV_REF (F)f)188       nullary_function(BOOST_THREAD_RV_REF(F) f):
189       impl(new impl_type<typename decay<F>::type>(thread_detail::decay_copy(boost::forward<F>(f))))
190       {}
191 
nullary_function(nullary_function const & other)192       nullary_function(nullary_function const& other) BOOST_NOEXCEPT :
193       impl(other.impl)
194       {
195       }
nullary_function(BOOST_THREAD_RV_REF (nullary_function)other)196       nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT :
197 #if defined BOOST_NO_CXX11_SMART_PTR
198       impl(BOOST_THREAD_RV(other).impl)
199       {
200         BOOST_THREAD_RV(other).impl.reset();
201       }
202 #else
203       impl(boost::move(other.impl))
204       {
205       }
206 #endif
nullary_function()207       nullary_function()
208         : impl()
209       {
210       }
~nullary_function()211       ~nullary_function()
212       {
213       }
214 
operator =(BOOST_THREAD_COPY_ASSIGN_REF (nullary_function)other)215       nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT
216       {
217         impl=other.impl;
218         return *this;
219       }
operator =(BOOST_THREAD_RV_REF (nullary_function)other)220       nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT
221       {
222 #if defined BOOST_NO_CXX11_SMART_PTR
223         impl=BOOST_THREAD_RV(other).impl;
224         BOOST_THREAD_RV(other).impl.reset();
225 #else
226         impl = boost::move(other.impl);
227 #endif
228         return *this;
229       }
230 
operator ()()231       R operator()()
232       { if (impl) return impl->call(); else return R();}
233 
234     };
235   }
236   BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function<F> BOOST_THREAD_DCL_MOVABLE_END
237 }
238 
239 #endif // header
240