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