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