get_or_pass.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. // <boost/thread/future.hpp>
  6. // class future<R>
  7. // R future::get_or(R&&);
  8. // R& future<R&>::get_or(R&);
  9. #define BOOST_THREAD_VERSION 4
  10. //#define BOOST_THREAD_USES_LOG
  11. #define BOOST_THREAD_USES_LOG_THREAD_ID
  12. #include <boost/thread/detail/log.hpp>
  13. #include <boost/thread/future.hpp>
  14. #include <boost/thread/thread.hpp>
  15. #include <boost/core/ref.hpp>
  16. #include <boost/detail/lightweight_test.hpp>
  17. #if defined BOOST_THREAD_USES_CHRONO
  18. #ifdef BOOST_MSVC
  19. #pragma warning(disable: 4127) // conditional expression is constant
  20. #endif
  21. namespace boost
  22. {
  23. template <typename T>
  24. struct wrap
  25. {
  26. wrap(T const& v) : value(v){}
  27. T value;
  28. };
  29. template <typename T>
  30. exception_ptr make_exception_ptr(T v) {
  31. return copy_exception(wrap<T>(v));
  32. }
  33. }
  34. void func1(boost::promise<int> p)
  35. {
  36. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  37. p.set_value(3);
  38. }
  39. void func2(boost::promise<int> p)
  40. {
  41. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  42. p.set_exception(boost::make_exception_ptr(3));
  43. }
  44. int j = 0;
  45. void func3(boost::promise<int&> p)
  46. {
  47. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  48. j = 5;
  49. p.set_value(j);
  50. }
  51. void func4(boost::promise<int&> p)
  52. {
  53. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  54. p.set_exception(boost::make_exception_ptr(3.5));
  55. }
  56. void func5(boost::promise<void> p)
  57. {
  58. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  59. p.set_value();
  60. }
  61. void func6(boost::promise<void> p)
  62. {
  63. boost::this_thread::sleep_for(boost::chrono::milliseconds(500));
  64. p.set_exception(boost::make_exception_ptr(4));
  65. }
  66. int main()
  67. {
  68. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  69. {
  70. typedef int T;
  71. {
  72. boost::promise<T> p;
  73. boost::future<T> f = p.get_future();
  74. #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
  75. boost::thread(func1, boost::move(p)).detach();
  76. #else
  77. p.set_value(3);
  78. #endif
  79. BOOST_TEST(f.valid());
  80. BOOST_TEST(f.get_or(4) == 3);
  81. #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
  82. BOOST_TEST(!f.valid());
  83. #endif
  84. }
  85. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  86. {
  87. boost::promise<T> p;
  88. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  89. boost::future<T> f = p.get_future();
  90. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  91. #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
  92. boost::thread(func2, boost::move(p)).detach();
  93. #else
  94. p.set_exception(boost::make_exception_ptr(3));
  95. #endif
  96. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  97. try
  98. {
  99. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  100. BOOST_TEST(f.valid());
  101. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  102. BOOST_TEST(f.get_or(4) == 4);
  103. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  104. }
  105. catch (...)
  106. {
  107. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  108. BOOST_TEST(false);
  109. }
  110. #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
  111. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  112. BOOST_TEST(!f.valid());
  113. #endif
  114. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  115. }
  116. }
  117. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  118. {
  119. typedef int& T;
  120. {
  121. boost::promise<T> p;
  122. boost::future<T> f = p.get_future();
  123. #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
  124. boost::thread(func3, boost::move(p)).detach();
  125. #else
  126. int j=5;
  127. p.set_value(j);
  128. #endif
  129. BOOST_TEST(f.valid());
  130. int k=4;
  131. BOOST_TEST(f.get_or(boost::ref(k)) == 5);
  132. #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
  133. BOOST_TEST(!f.valid());
  134. #endif
  135. }
  136. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  137. {
  138. boost::promise<T> p;
  139. boost::future<T> f = p.get_future();
  140. #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD)
  141. boost::thread(func4, boost::move(p)).detach();
  142. #else
  143. p.set_exception(boost::make_exception_ptr(3.5));
  144. #endif
  145. try
  146. {
  147. BOOST_TEST(f.valid());
  148. int j=4;
  149. BOOST_TEST(f.get_or(boost::ref(j)) == 4);
  150. }
  151. catch (...)
  152. {
  153. BOOST_TEST(false);
  154. }
  155. #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET
  156. BOOST_TEST(!f.valid());
  157. #endif
  158. }
  159. }
  160. BOOST_THREAD_LOG << BOOST_THREAD_END_LOG;
  161. return boost::report_errors();
  162. }
  163. #else
  164. #error "Test not applicable: BOOST_THREAD_USES_CHRONO not defined for this platform as not supported"
  165. #endif