emulations.qbk 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. [/
  2. (C) Copyright 20012 Vicente J. Botet Escriba.
  3. Distributed under the Boost Software License, Version 1.0.
  4. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. ]
  7. [section:emulations Emulations]
  8. [section:delete `=delete` emulation]
  9. C++11 allows to delete some implicitly generated functions as constructors and assignment using '= delete' as in
  10. public:
  11. thread(thread const&) = delete;
  12. On compilers not supporting this feature, Boost.Thread relays on a partial simulation, it declares the function as private without definition.
  13. private:
  14. thread(thread &);
  15. The emulation is partial as the private function can be used for overload resolution for some compilers and prefer it to other overloads that need a conversion. See below the consequences on the move semantic emulation.
  16. [endsect]
  17. [section:move Move semantics]
  18. In order to implement Movable classes, move parameters and return types Boost.Thread uses the rvalue reference when the compiler support it.
  19. On compilers not supporting it Boost.Thread uses either the emulation provided by Boost.Move or the emulation provided by the previous versions of Boost.Thread depending whether `BOOST_THREAD_USES_MOVE` is defined or not. This macros is unset by default when `BOOST_THREAD_VERSION` is 2. Since `BOOST_THREAD_VERSION` 3, `BOOST_THREAD_USES_MOVE` is defined.
  20. [section:deprecated Deprecated Version 2 interface]
  21. Previous to version 1.50, Boost.Thread make use of its own move semantic emulation which had more limitations than the provided by Boost.Move. In addition, it is of interest of the whole Boost community that Boost.Thread uses Boost.Move so that boost::thread can be stored on Movable aware containers.
  22. To preserve backward compatibility at least during some releases, Boost.Thread allows the user to use the deprecated move semantic emulation defining BOOST_THREAD_DONT_USE_MOVE.
  23. Many aspects of move semantics can be emulated for compilers not supporting rvalue references and Boost.Thread legacy offers tools for that purpose.
  24. [section:Helper Helpers class and function]
  25. Next follows the interface of the legacy move semantic helper class and function.
  26. namespace boost
  27. {
  28. namespace detail
  29. {
  30. template<typename T>
  31. struct thread_move_t
  32. {
  33. explicit thread_move_t(T& t_);
  34. T& operator*() const;
  35. T* operator->() const;
  36. private:
  37. void operator=(thread_move_t&);
  38. };
  39. }
  40. template<typename T>
  41. boost::detail::thread_move_t<T> move(boost::detail::thread_move_t<T> t);
  42. }
  43. [endsect]
  44. [section:movable Movable emulation]
  45. We can write a MovableOny class as follows. You just need to follow these simple steps:
  46. * Add a conversion to the `detail::thread_move_t<classname>`
  47. * Make the copy constructor private.
  48. * Write a constructor taking the parameter as `detail::thread_move_t<classname>`
  49. * Write an assignment taking the parameter as `detail::thread_move_t<classname>`
  50. For example the thread class defines the following:
  51. class thread
  52. {
  53. // ...
  54. private:
  55. thread(thread&);
  56. thread& operator=(thread&);
  57. public:
  58. detail::thread_move_t<thread> move()
  59. {
  60. detail::thread_move_t<thread> x(*this);
  61. return x;
  62. }
  63. operator detail::thread_move_t<thread>()
  64. {
  65. return move();
  66. }
  67. thread(detail::thread_move_t<thread> x)
  68. {
  69. thread_info=x->thread_info;
  70. x->thread_info.reset();
  71. }
  72. thread& operator=(detail::thread_move_t<thread> x)
  73. {
  74. thread new_thread(x);
  75. swap(new_thread);
  76. return *this;
  77. }
  78. // ...
  79. };
  80. [endsect]
  81. [endsect]
  82. [section:portable Portable interface]
  83. In order to make the library code portable Boost.Thread uses some macros that will use either the ones provided by Boost.Move or the deprecated move semantics provided by previous versions of Boost.Thread.
  84. See the Boost.Move documentation for a complete description on how to declare new Movable classes and its limitations.
  85. * `BOOST_THREAD_RV_REF(TYPE)` is the equivalent of `BOOST_RV_REF(TYPE)`
  86. * `BOOST_THREAD_RV_REF_BEG` is the equivalent of `BOOST_RV_REF_BEG(TYPE)`
  87. * `BOOST_THREAD_RV_REF_END` is the equivalent of `BOOST_RV_REF_END(TYPE)`
  88. * `BOOST_THREAD_FWD_REF(TYPE)` is the equivalent of `BOOST_FWD_REF(TYPE)
  89. In addition the following macros are needed to make the code portable:
  90. * `BOOST_THREAD_RV(V)` macro to access the rvalue from a BOOST_THREAD_RV_REF(TYPE),
  91. * `BOOST_THREAD_MAKE_RV_REF(RVALUE)` makes a rvalue.
  92. * `BOOST_THREAD_DCL_MOVABLE(CLASS)` to avoid conflicts with Boost.Move
  93. * `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END` are variant of `BOOST_THREAD_DCL_MOVABLE` when the parameter is a template instantiation.
  94. Other macros are provided and must be included on the public section:
  95. * `BOOST_THREAD_NO_COPYABLE` declares a class no-copyable either deleting the copy constructors and copy assignment or moving them to the private section.
  96. * `BOOST_THREAD_MOVABLE(CLASS)` declares all the implicit conversions to an rvalue-reference.
  97. * `BOOST_THREAD_MOVABLE_ONLY(CLASS)` is the equivalent of `BOOST_MOVABLE_BUT_NOT_COPYABLE(CLASS)`
  98. * `BOOST_THREAD_COPYABLE_AND_MOVABLE(CLASS)` is the equivalent of `BOOST_COPYABLE_AND_MOVABLE(CLASS)`
  99. [section:NO_COPYABLE `BOOST_THREAD_NO_COPYABLE(CLASS)`]
  100. This macro marks a class as no copyable, disabling copy construction and assignment.
  101. [endsect]
  102. [section:MOVABLE `BOOST_THREAD_MOVABLE(CLASS)`]
  103. This macro marks a class as movable, declaring all the implicit conversions to an rvalue-reference.
  104. [endsect]
  105. [section:MOVABLE_ONLY `BOOST_THREAD_MOVABLE_ONLY(CLASS)`]
  106. This macro marks a type as movable but not copyable, disabling copy construction and assignment. The user will need to write a move constructor/assignment to fully write a movable but not copyable class.
  107. [endsect]
  108. [section:COPYABLE_AND_MOVABLE `BOOST_THREAD_COPYABLE_AND_MOVABLE(CLASS)`]
  109. This macro marks a type as copyable and movable. The user will need to write a move constructor/assignment and a copy assignment to fully write a copyable and movable class.
  110. [endsect]
  111. [section:RV_REF `BOOST_THREAD_RV_REF(TYPE)`, `BOOST_THREAD_RV_REF_BEG` and `BOOST_THREAD_RV_REF_END`]
  112. This macro is used to achieve portable syntax in move constructors and assignments for classes marked as `BOOST_THREAD_COPYABLE_AND_MOVABLE` or `BOOST_THREAD_MOVABLE_ONLY`.
  113. `BOOST_THREAD_RV_REF_BEG` and `BOOST_THREAD_RV_REF_END` are used when the parameter end with a `>` to avoid the compiler error.
  114. [endsect]
  115. [section:RV `BOOST_THREAD_RV(V)`]
  116. While Boost.Move emulation allows to access an rvalue reference `BOOST_THREAD_RV_REF(TYPE)` using the dot operator, the legacy defines the `operator->`. We need then a macro `BOOST_THREAD_RV` that mask this difference. E.g.
  117. thread(BOOST_THREAD_RV_REF(thread) x)
  118. {
  119. thread_info=BOOST_THREAD_RV(x).thread_info;
  120. BOOST_THREAD_RV(x).thread_info.reset();
  121. }
  122. The use of this macros has reduced considerably the size of the Boost.Thread move related code.
  123. [endsect]
  124. [section:MAKE_RV_REF `BOOST_THREAD_MAKE_RV_REF(RVALUE)`]
  125. While Boost.Move is the best C++03 move emulation there are some limitations that impact the way the library can be used.
  126. For example, with the following declarations
  127. class thread {
  128. // ...
  129. private:
  130. thread(thread &);
  131. public:
  132. thread(rv<thread>&);
  133. // ...
  134. };
  135. This could not work on some compilers even if thread is convertible to `rv<thread>` because the compiler prefers the private copy constructor.
  136. thread mkth()
  137. {
  138. return thread(f);
  139. }
  140. On these compilers we need to use instead an explicit conversion. The library provides a move member function that allows to workaround the issue.
  141. thread mkth()
  142. {
  143. return thread(f).move();
  144. }
  145. Note that `::boost::move` can not be used in this case as thread is not implicitly convertible to `thread&`.
  146. thread mkth()
  147. {
  148. return ::boost::move(thread(f));
  149. }
  150. To make the code portable Boost.Thread the user needs to use a macro `BOOST_THREAD_MAKE_RV_REF` that can be used as in
  151. thread mkth()
  152. {
  153. return BOOST_THREAD_MAKE_RV_REF(thread(f));
  154. }
  155. Note that this limitation is shared also by the legacy Boost.Thread move emulation.
  156. [endsect]
  157. [section:DCL_MOVABLE `BOOST_THREAD_DCL_MOVABLE`, `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END`]
  158. As Boost.Move defines also the `boost::move` function we need to specialize the `has_move_emulation_enabled_aux` metafunction.
  159. template <>
  160. struct has_move_emulation_enabled_aux<thread>
  161. : BOOST_MOVE_BOOST_NS::integral_constant<bool, true>
  162. {};
  163. so that the following Boost.Move overload is disabled
  164. template <class T>
  165. inline typename BOOST_MOVE_BOOST_NS::disable_if<has_move_emulation_enabled_aux<T>, T&>::type move(T& x);
  166. The macros `BOOST_THREAD_DCL_MOVABLE(CLASS)`, `BOOST_THREAD_DCL_MOVABLE_BEG(T1)` and `BOOST_THREAD_DCL_MOVABLE_END` are used for this purpose. E.g.
  167. BOOST_THREAD_DCL_MOVABLE(thread)
  168. and
  169. BOOST_THREAD_DCL_MOVABLE_BEG(T) promise<T> BOOST_THREAD_DCL_MOVABLE_END
  170. [endsect]
  171. [endsect]
  172. [endsect]
  173. [section:bool_explicit_conversion Bool explicit conversion]
  174. Locks provide an explicit bool conversion operator when the compiler provides them.
  175. explicit operator bool() const;
  176. The library provides un implicit conversion to an undefined type that can be used as a conditional expression.
  177. #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
  178. operator ``['unspecified-bool-type]``() const;
  179. bool operator!() const;
  180. #else
  181. explicit operator bool() const;
  182. #endif
  183. The user should use the lock.owns_lock() when an explicit conversion is required.
  184. [section:bool_conversion `operator `['unspecified-bool-type]`() const`]
  185. [variablelist
  186. [[Returns:] [If __owns_lock_ref__ would return `true`, a value that evaluates to
  187. `true` in boolean contexts, otherwise a value that evaluates to `false` in
  188. boolean contexts.]]
  189. [[Throws:] [Nothing.]]
  190. ]
  191. [endsect]
  192. [section:operator_not `bool operator!() const`]
  193. [variablelist
  194. [[Returns:] [`!` __owns_lock_ref__.]]
  195. [[Throws:] [Nothing.]]
  196. ]
  197. [endsect]
  198. [endsect]
  199. [section:scoped_enums Scoped Enums]
  200. Some of the enumerations defined in the standard library are scoped enums.
  201. On compilers that don't support them, the library uses a class to wrap the underlying type. Instead of
  202. enum class future_errc
  203. {
  204. broken_promise,
  205. future_already_retrieved,
  206. promise_already_satisfied,
  207. no_state
  208. };
  209. the library declare these types as
  210. BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc)
  211. {
  212. broken_promise,
  213. future_already_retrieved,
  214. promise_already_satisfied,
  215. no_state
  216. }
  217. BOOST_SCOPED_ENUM_DECLARE_END(future_errc)
  218. These macros allows to use 'future_errc' in almost all the cases as a scoped enum.
  219. There are however some limitations:
  220. * The type is not a C++ enum, so 'is_enum<future_errc>' will be false_type.
  221. * The emulated scoped enum can not be used in switch nor in template arguments. For these cases the user needs to use some macros.
  222. Instead of
  223. switch (ev)
  224. {
  225. case future_errc::broken_promise:
  226. // ...
  227. use
  228. switch (boost::native_value(ev))
  229. {
  230. case future_errc::broken_promise:
  231. And instead of
  232. #ifdef BOOST_NO_CXX11_SCOPED_ENUMS
  233. template <>
  234. struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc> : public true_type { };
  235. #endif
  236. use
  237. #ifdef BOOST_NO_CXX11_SCOPED_ENUMS
  238. template <>
  239. struct BOOST_SYMBOL_VISIBLE is_error_code_enum<future_errc::enum_type> : public true_type { };
  240. #endif
  241. [endsect]
  242. [endsect]