nullary_function.hpp 5.6 KB

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