nullary_function.hpp 5.3 KB

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