test_promise_dispatch.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. // (C) Copyright 2008-10 Anthony Williams
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #include <utility>
  7. #include <memory>
  8. #include <stdexcept>
  9. #include <string>
  10. #include <boost/test/unit_test.hpp>
  11. #include <boost/fiber/all.hpp>
  12. int gi = 7;
  13. struct my_exception : public std::runtime_error {
  14. my_exception() :
  15. std::runtime_error("my_exception") {
  16. }
  17. };
  18. struct A {
  19. A() = default;
  20. A( A const&) = delete;
  21. A( A &&) = default;
  22. A & operator=( A const&) = delete;
  23. A & operator=( A &&) = default;
  24. int value{ 0 };
  25. };
  26. void fn1( boost::fibers::promise< int > * p, int i) {
  27. boost::this_fiber::yield();
  28. p->set_value( i);
  29. }
  30. void fn2() {
  31. boost::fibers::promise< int > p;
  32. boost::fibers::future< int > f( p.get_future() );
  33. boost::this_fiber::yield();
  34. boost::fibers::fiber( boost::fibers::launch::dispatch, fn1, & p, 7).detach();
  35. boost::this_fiber::yield();
  36. BOOST_CHECK( 7 == f.get() );
  37. }
  38. int fn3() {
  39. return 3;
  40. }
  41. void fn4() {
  42. }
  43. int fn5() {
  44. boost::throw_exception( my_exception() );
  45. return 3;
  46. }
  47. void fn6() {
  48. boost::throw_exception( my_exception() );
  49. }
  50. int & fn7() {
  51. return gi;
  52. }
  53. int fn8( int i) {
  54. return i;
  55. }
  56. A fn9() {
  57. A a;
  58. a.value = 3;
  59. return a;
  60. }
  61. A fn10() {
  62. boost::throw_exception( my_exception() );
  63. return A();
  64. }
  65. // promise
  66. void test_promise_create() {
  67. // use std::allocator<> as default
  68. boost::fibers::promise< int > p1;
  69. // use std::allocator<> as user defined
  70. std::allocator< boost::fibers::promise< int > > alloc;
  71. boost::fibers::promise< int > p2( std::allocator_arg, alloc);
  72. }
  73. void test_promise_create_ref() {
  74. // use std::allocator<> as default
  75. boost::fibers::promise< int& > p1;
  76. // use std::allocator<> as user defined
  77. std::allocator< boost::fibers::promise< int& > > alloc;
  78. boost::fibers::promise< int& > p2( std::allocator_arg, alloc);
  79. }
  80. void test_promise_create_void() {
  81. // use std::allocator<> as default
  82. boost::fibers::promise< void > p1;
  83. // use std::allocator<> as user defined
  84. std::allocator< boost::fibers::promise< void > > alloc;
  85. boost::fibers::promise< void > p2( std::allocator_arg, alloc);
  86. }
  87. void test_promise_move() {
  88. boost::fibers::promise< int > p1;
  89. // move construction
  90. boost::fibers::promise< int > p2( std::move( p1) );
  91. // move assigment
  92. p1 = std::move( p2);
  93. }
  94. void test_promise_move_ref() {
  95. boost::fibers::promise< int& > p1;
  96. // move construction
  97. boost::fibers::promise< int& > p2( std::move( p1) );
  98. // move assigment
  99. p1 = std::move( p2);
  100. }
  101. void test_promise_move_void() {
  102. boost::fibers::promise< void > p1;
  103. // move construction
  104. boost::fibers::promise< void > p2( std::move( p1) );
  105. // move assigment
  106. p1 = std::move( p2);
  107. }
  108. void test_promise_swap() {
  109. boost::fibers::promise< int > p1;
  110. // move construction
  111. boost::fibers::promise< int > p2( std::move( p1) );
  112. // swap
  113. p1.swap( p2);
  114. }
  115. void test_promise_swap_ref() {
  116. boost::fibers::promise< int& > p1;
  117. // move construction
  118. boost::fibers::promise< int& > p2( std::move( p1) );
  119. // swap
  120. p1.swap( p2);
  121. }
  122. void test_promise_swap_void() {
  123. boost::fibers::promise< void > p1;
  124. // move construction
  125. boost::fibers::promise< void > p2( std::move( p1) );
  126. // swap
  127. p1.swap( p2);
  128. }
  129. void test_promise_get_future() {
  130. boost::fibers::promise< int > p1;
  131. // retrieve future
  132. boost::fibers::future< int > f1 = p1.get_future();
  133. BOOST_CHECK( f1.valid() );
  134. // retrieve future a second time
  135. bool thrown = false;
  136. try {
  137. f1 = p1.get_future();
  138. } catch ( boost::fibers::future_already_retrieved const&) {
  139. thrown = true;
  140. }
  141. BOOST_CHECK( thrown);
  142. // move construction
  143. boost::fibers::promise< int > p2( std::move( p1) );
  144. // retrieve future from uninitialized
  145. thrown = false;
  146. try {
  147. f1 = p1.get_future();
  148. } catch ( boost::fibers::promise_uninitialized const&) {
  149. thrown = true;
  150. }
  151. BOOST_CHECK( thrown);
  152. }
  153. void test_promise_get_future_ref() {
  154. boost::fibers::promise< int& > p1;
  155. // retrieve future
  156. boost::fibers::future< int& > f1 = p1.get_future();
  157. BOOST_CHECK( f1.valid() );
  158. // retrieve future a second time
  159. bool thrown = false;
  160. try {
  161. f1 = p1.get_future();
  162. } catch ( boost::fibers::future_already_retrieved const&) {
  163. thrown = true;
  164. }
  165. BOOST_CHECK( thrown);
  166. // move construction
  167. boost::fibers::promise< int& > p2( std::move( p1) );
  168. // retrieve future from uninitialized
  169. thrown = false;
  170. try {
  171. f1 = p1.get_future();
  172. } catch ( boost::fibers::promise_uninitialized const&) {
  173. thrown = true;
  174. }
  175. BOOST_CHECK( thrown);
  176. }
  177. void test_promise_get_future_void() {
  178. boost::fibers::promise< void > p1;
  179. // retrieve future
  180. boost::fibers::future< void > f1 = p1.get_future();
  181. BOOST_CHECK( f1.valid() );
  182. // retrieve future a second time
  183. bool thrown = false;
  184. try {
  185. f1 = p1.get_future();
  186. } catch ( boost::fibers::future_already_retrieved const&) {
  187. thrown = true;
  188. }
  189. BOOST_CHECK( thrown);
  190. // move construction
  191. boost::fibers::promise< void > p2( std::move( p1) );
  192. // retrieve future from uninitialized
  193. thrown = false;
  194. try {
  195. f1 = p1.get_future();
  196. } catch ( boost::fibers::promise_uninitialized const&) {
  197. thrown = true;
  198. }
  199. BOOST_CHECK( thrown);
  200. }
  201. void test_promise_set_value() {
  202. // promise takes a copyable as return type
  203. boost::fibers::promise< int > p1;
  204. boost::fibers::future< int > f1 = p1.get_future();
  205. BOOST_CHECK( f1.valid() );
  206. // copy value
  207. p1.set_value( 7);
  208. BOOST_CHECK( 7 == f1.get() );
  209. // set value a second time
  210. bool thrown = false;
  211. try {
  212. p1.set_value( 11);
  213. } catch ( boost::fibers::promise_already_satisfied const&) {
  214. thrown = true;
  215. }
  216. BOOST_CHECK( thrown);
  217. }
  218. void test_promise_set_value_move() {
  219. // promise takes a copyable as return type
  220. boost::fibers::promise< A > p1;
  221. boost::fibers::future< A > f1 = p1.get_future();
  222. BOOST_CHECK( f1.valid() );
  223. // move value
  224. A a1; a1.value = 7;
  225. p1.set_value( std::move( a1) );
  226. A a2 = f1.get();
  227. BOOST_CHECK( 7 == a2.value);
  228. // set value a second time
  229. bool thrown = false;
  230. try {
  231. A a;
  232. p1.set_value( std::move( a) );
  233. } catch ( boost::fibers::promise_already_satisfied const&) {
  234. thrown = true;
  235. }
  236. BOOST_CHECK( thrown);
  237. }
  238. void test_promise_set_value_ref() {
  239. // promise takes a reference as return type
  240. boost::fibers::promise< int& > p1;
  241. boost::fibers::future< int& > f1 = p1.get_future();
  242. BOOST_CHECK( f1.valid() );
  243. // copy value
  244. int i = 7;
  245. p1.set_value( i);
  246. int & j = f1.get();
  247. BOOST_CHECK( &i == &j);
  248. // set value a second time
  249. bool thrown = false;
  250. try {
  251. p1.set_value( i);
  252. } catch ( boost::fibers::promise_already_satisfied const&) {
  253. thrown = true;
  254. }
  255. BOOST_CHECK( thrown);
  256. }
  257. void test_promise_set_value_void() {
  258. // promise takes a copyable as return type
  259. boost::fibers::promise< void > p1;
  260. boost::fibers::future< void > f1 = p1.get_future();
  261. BOOST_CHECK( f1.valid() );
  262. // set void
  263. p1.set_value();
  264. f1.get();
  265. // set value a second time
  266. bool thrown = false;
  267. try {
  268. p1.set_value();
  269. } catch ( boost::fibers::promise_already_satisfied const&) {
  270. thrown = true;
  271. }
  272. BOOST_CHECK( thrown);
  273. }
  274. void test_promise_set_exception() {
  275. boost::fibers::promise< int > p1;
  276. boost::fibers::future< int > f1 = p1.get_future();
  277. BOOST_CHECK( f1.valid() );
  278. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  279. // set exception a second time
  280. bool thrown = false;
  281. try {
  282. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  283. } catch ( boost::fibers::promise_already_satisfied const&) {
  284. thrown = true;
  285. }
  286. BOOST_CHECK( thrown);
  287. // set value
  288. thrown = false;
  289. try
  290. { p1.set_value( 11); }
  291. catch ( boost::fibers::promise_already_satisfied const&)
  292. { thrown = true; }
  293. BOOST_CHECK( thrown);
  294. }
  295. void test_promise_set_exception_ref() {
  296. boost::fibers::promise< int& > p1;
  297. boost::fibers::future< int& > f1 = p1.get_future();
  298. BOOST_CHECK( f1.valid() );
  299. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  300. // set exception a second time
  301. bool thrown = false;
  302. try {
  303. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  304. } catch ( boost::fibers::promise_already_satisfied const&) {
  305. thrown = true;
  306. }
  307. BOOST_CHECK( thrown);
  308. // set value
  309. thrown = false;
  310. int i = 11;
  311. try {
  312. p1.set_value( i);
  313. } catch ( boost::fibers::promise_already_satisfied const&) {
  314. thrown = true;
  315. }
  316. BOOST_CHECK( thrown);
  317. }
  318. void test_promise_set_exception_void() {
  319. boost::fibers::promise< void > p1;
  320. boost::fibers::future< void > f1 = p1.get_future();
  321. BOOST_CHECK( f1.valid() );
  322. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  323. // set exception a second time
  324. bool thrown = false;
  325. try {
  326. p1.set_exception( std::make_exception_ptr( my_exception() ) );
  327. } catch ( boost::fibers::promise_already_satisfied const&) {
  328. thrown = true;
  329. }
  330. BOOST_CHECK( thrown);
  331. // set value
  332. thrown = false;
  333. try {
  334. p1.set_value();
  335. } catch ( boost::fibers::promise_already_satisfied const&) {
  336. thrown = true;
  337. }
  338. BOOST_CHECK( thrown);
  339. }
  340. boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
  341. boost::unit_test_framework::test_suite* test =
  342. BOOST_TEST_SUITE("Boost.Fiber: promise test suite");
  343. test->add(BOOST_TEST_CASE(test_promise_create));
  344. test->add(BOOST_TEST_CASE(test_promise_create_ref));
  345. test->add(BOOST_TEST_CASE(test_promise_create_void));
  346. test->add(BOOST_TEST_CASE(test_promise_move));
  347. test->add(BOOST_TEST_CASE(test_promise_move_ref));
  348. test->add(BOOST_TEST_CASE(test_promise_move_void));
  349. test->add(BOOST_TEST_CASE(test_promise_swap));
  350. test->add(BOOST_TEST_CASE(test_promise_swap_ref));
  351. test->add(BOOST_TEST_CASE(test_promise_swap_void));
  352. test->add(BOOST_TEST_CASE(test_promise_get_future));
  353. test->add(BOOST_TEST_CASE(test_promise_get_future_ref));
  354. test->add(BOOST_TEST_CASE(test_promise_get_future_void));
  355. test->add(BOOST_TEST_CASE(test_promise_set_value));
  356. test->add(BOOST_TEST_CASE(test_promise_set_value_move));
  357. test->add(BOOST_TEST_CASE(test_promise_set_value_ref));
  358. test->add(BOOST_TEST_CASE(test_promise_set_value_void));
  359. test->add(BOOST_TEST_CASE(test_promise_set_exception));
  360. test->add(BOOST_TEST_CASE(test_promise_set_exception_ref));
  361. test->add(BOOST_TEST_CASE(test_promise_set_exception_void));
  362. return test;
  363. }