test_shared_future_post.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. // (C) Copyright 2008-10 Anthony Williams
  2. // 2015 Oliver Kowalke
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. #include <chrono>
  8. #include <memory>
  9. #include <stdexcept>
  10. #include <string>
  11. #include <utility>
  12. #include <boost/test/unit_test.hpp>
  13. #include <boost/fiber/all.hpp>
  14. typedef std::chrono::milliseconds ms;
  15. typedef std::chrono::high_resolution_clock Clock;
  16. int gi = 7;
  17. struct my_exception : public std::runtime_error {
  18. my_exception() :
  19. std::runtime_error("my_exception") {
  20. }
  21. };
  22. struct A {
  23. A() = default;
  24. A( A const&) = delete;
  25. A( A &&) = default;
  26. A & operator=( A const&) = delete;
  27. A & operator=( A &&) = default;
  28. int value;
  29. };
  30. void fn1( boost::fibers::promise< int > * p, int i) {
  31. boost::this_fiber::yield();
  32. p->set_value( i);
  33. }
  34. void fn2() {
  35. boost::fibers::promise< int > p;
  36. boost::fibers::shared_future< int > f( p.get_future().share() );
  37. boost::this_fiber::yield();
  38. boost::fibers::fiber( boost::fibers::launch::post, fn1, & p, 7).detach();
  39. boost::this_fiber::yield();
  40. BOOST_CHECK( 7 == f.get() );
  41. }
  42. int fn3() {
  43. return 3;
  44. }
  45. void fn4() {
  46. }
  47. int fn5() {
  48. boost::throw_exception( my_exception() );
  49. return 3;
  50. }
  51. void fn6() {
  52. boost::throw_exception( my_exception() );
  53. }
  54. int & fn7() {
  55. return gi;
  56. }
  57. int fn8( int i) {
  58. return i;
  59. }
  60. A fn9() {
  61. A a;
  62. a.value = 3;
  63. return a;
  64. }
  65. A fn10() {
  66. boost::throw_exception( my_exception() );
  67. return A();
  68. }
  69. void fn11( boost::fibers::promise< int > p) {
  70. boost::this_fiber::sleep_for( ms(500) );
  71. p.set_value(3);
  72. }
  73. void fn12( boost::fibers::promise< int& > p) {
  74. boost::this_fiber::sleep_for( ms(500) );
  75. gi = 5;
  76. p.set_value( gi);
  77. }
  78. void fn13( boost::fibers::promise< void > p) {
  79. boost::this_fiber::sleep_for( ms(500) );
  80. p.set_value();
  81. }
  82. // shared_future
  83. void test_shared_future_create() {
  84. {
  85. // default constructed and assigned shared_future is not valid
  86. boost::fibers::shared_future< int > f1;
  87. boost::fibers::shared_future< int > f2 = f1;
  88. BOOST_CHECK( ! f1.valid() );
  89. BOOST_CHECK( ! f2.valid() );
  90. }
  91. {
  92. // shared_future retrieved from promise is valid
  93. boost::fibers::promise< int > p;
  94. boost::fibers::shared_future< int > f1 = p.get_future();
  95. boost::fibers::shared_future< int > f2 = f1;
  96. BOOST_CHECK( f1.valid() );
  97. BOOST_CHECK( f2.valid() );
  98. }
  99. }
  100. void test_shared_future_create_ref() {
  101. {
  102. // default constructed and assigned shared_future is not valid
  103. boost::fibers::shared_future< int& > f1;
  104. boost::fibers::shared_future< int& > f2 = f1;
  105. BOOST_CHECK( ! f1.valid() );
  106. BOOST_CHECK( ! f2.valid() );
  107. }
  108. {
  109. // shared_future retrieved from promise is valid
  110. boost::fibers::promise< int& > p;
  111. boost::fibers::shared_future< int& > f1 = p.get_future();
  112. boost::fibers::shared_future< int& > f2 = f1;
  113. BOOST_CHECK( f1.valid() );
  114. BOOST_CHECK( f2.valid() );
  115. }
  116. }
  117. void test_shared_future_create_void() {
  118. {
  119. // default constructed and assigned shared_future is not valid
  120. boost::fibers::shared_future< void > f1;
  121. boost::fibers::shared_future< void > f2 = f1;
  122. BOOST_CHECK( ! f1.valid() );
  123. BOOST_CHECK( ! f2.valid() );
  124. }
  125. {
  126. // shared_future retrieved from promise is valid
  127. boost::fibers::promise< void > p;
  128. boost::fibers::shared_future< void > f1 = p.get_future();
  129. boost::fibers::shared_future< void > f2 = f1;
  130. BOOST_CHECK( f1.valid() );
  131. BOOST_CHECK( f2.valid() );
  132. }
  133. }
  134. void test_shared_future_get() {
  135. // future retrieved from promise is valid (if it is the first)
  136. boost::fibers::promise< int > p1;
  137. p1.set_value( 7);
  138. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  139. BOOST_CHECK( f1.valid() );
  140. // get
  141. BOOST_CHECK( ! f1.get_exception_ptr() );
  142. BOOST_CHECK( 7 == f1.get() );
  143. BOOST_CHECK( f1.valid() );
  144. // throw broken_promise if promise is destroyed without set
  145. {
  146. boost::fibers::promise< int > p2;
  147. f1 = p2.get_future().share();
  148. }
  149. bool thrown = false;
  150. try {
  151. f1.get();
  152. } catch ( boost::fibers::broken_promise const&) {
  153. thrown = true;
  154. }
  155. BOOST_CHECK( f1.valid() );
  156. BOOST_CHECK( thrown);
  157. }
  158. void test_shared_future_get_move() {
  159. // future retrieved from promise is valid (if it is the first)
  160. boost::fibers::promise< A > p1;
  161. A a; a.value = 7;
  162. p1.set_value( std::move( a) );
  163. boost::fibers::shared_future< A > f1 = p1.get_future().share();
  164. BOOST_CHECK( f1.valid() );
  165. // get
  166. BOOST_CHECK( ! f1.get_exception_ptr() );
  167. BOOST_CHECK( 7 == f1.get().value);
  168. BOOST_CHECK( f1.valid() );
  169. // throw broken_promise if promise is destroyed without set
  170. {
  171. boost::fibers::promise< A > p2;
  172. f1 = p2.get_future().share();
  173. }
  174. bool thrown = false;
  175. try {
  176. f1.get();
  177. } catch ( boost::fibers::broken_promise const&) {
  178. thrown = true;
  179. }
  180. BOOST_CHECK( f1.valid() );
  181. BOOST_CHECK( thrown);
  182. }
  183. void test_shared_future_get_ref() {
  184. // future retrieved from promise is valid (if it is the first)
  185. boost::fibers::promise< int& > p1;
  186. int i = 7;
  187. p1.set_value( i);
  188. boost::fibers::shared_future< int& > f1 = p1.get_future().share();
  189. BOOST_CHECK( f1.valid() );
  190. // get
  191. BOOST_CHECK( ! f1.get_exception_ptr() );
  192. int & j = f1.get();
  193. BOOST_CHECK( &i == &j);
  194. BOOST_CHECK( f1.valid() );
  195. // throw broken_promise if promise is destroyed without set
  196. {
  197. boost::fibers::promise< int& > p2;
  198. f1 = p2.get_future().share();
  199. }
  200. bool thrown = false;
  201. try {
  202. f1.get();
  203. } catch ( boost::fibers::broken_promise const&) {
  204. thrown = true;
  205. }
  206. BOOST_CHECK( f1.valid() );
  207. BOOST_CHECK( thrown);
  208. }
  209. void test_shared_future_get_void() {
  210. // future retrieved from promise is valid (if it is the first)
  211. boost::fibers::promise< void > p1;
  212. p1.set_value();
  213. boost::fibers::shared_future< void > f1 = p1.get_future().share();
  214. BOOST_CHECK( f1.valid() );
  215. // get
  216. BOOST_CHECK( ! f1.get_exception_ptr() );
  217. f1.get();
  218. BOOST_CHECK( f1.valid() );
  219. // throw broken_promise if promise is destroyed without set
  220. {
  221. boost::fibers::promise< void > p2;
  222. f1 = p2.get_future().share();
  223. }
  224. bool thrown = false;
  225. try {
  226. f1.get();
  227. } catch ( boost::fibers::broken_promise const&) {
  228. thrown = true;
  229. }
  230. BOOST_CHECK( f1.valid() );
  231. BOOST_CHECK( thrown);
  232. }
  233. void test_future_share() {
  234. // future retrieved from promise is valid (if it is the first)
  235. boost::fibers::promise< int > p1;
  236. int i = 7;
  237. p1.set_value( i);
  238. boost::fibers::future< int > f1 = p1.get_future();
  239. BOOST_CHECK( f1.valid() );
  240. // share
  241. boost::fibers::shared_future< int > sf1 = f1.share();
  242. BOOST_CHECK( sf1.valid() );
  243. BOOST_CHECK( ! f1.valid() );
  244. // get
  245. BOOST_CHECK( ! sf1.get_exception_ptr() );
  246. int j = sf1.get();
  247. BOOST_CHECK_EQUAL( i, j);
  248. BOOST_CHECK( sf1.valid() );
  249. }
  250. void test_future_share_ref() {
  251. // future retrieved from promise is valid (if it is the first)
  252. boost::fibers::promise< int& > p1;
  253. int i = 7;
  254. p1.set_value( i);
  255. boost::fibers::future< int& > f1 = p1.get_future();
  256. BOOST_CHECK( f1.valid() );
  257. // share
  258. boost::fibers::shared_future< int& > sf1 = f1.share();
  259. BOOST_CHECK( sf1.valid() );
  260. BOOST_CHECK( ! f1.valid() );
  261. // get
  262. BOOST_CHECK( ! sf1.get_exception_ptr() );
  263. int & j = sf1.get();
  264. BOOST_CHECK( &i == &j);
  265. BOOST_CHECK( sf1.valid() );
  266. }
  267. void test_future_share_void() {
  268. // future retrieved from promise is valid (if it is the first)
  269. boost::fibers::promise< void > p1;
  270. p1.set_value();
  271. boost::fibers::future< void > f1 = p1.get_future();
  272. BOOST_CHECK( f1.valid() );
  273. // share
  274. boost::fibers::shared_future< void > sf1 = f1.share();
  275. BOOST_CHECK( sf1.valid() );
  276. BOOST_CHECK( ! f1.valid() );
  277. // get
  278. BOOST_CHECK( ! sf1.get_exception_ptr() );
  279. sf1.get();
  280. BOOST_CHECK( sf1.valid() );
  281. }
  282. void test_shared_future_wait() {
  283. // future retrieved from promise is valid (if it is the first)
  284. boost::fibers::promise< int > p1;
  285. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  286. // wait on future
  287. p1.set_value( 7);
  288. f1.wait();
  289. BOOST_CHECK( 7 == f1.get() );
  290. }
  291. void test_shared_future_wait_ref() {
  292. // future retrieved from promise is valid (if it is the first)
  293. boost::fibers::promise< int& > p1;
  294. boost::fibers::shared_future< int& > f1 = p1.get_future().share();
  295. // wait on future
  296. int i = 7;
  297. p1.set_value( i);
  298. f1.wait();
  299. int & j = f1.get();
  300. BOOST_CHECK( &i == &j);
  301. }
  302. void test_shared_future_wait_void() {
  303. // future retrieved from promise is valid (if it is the first)
  304. boost::fibers::promise< void > p1;
  305. boost::fibers::shared_future< void > f1 = p1.get_future().share();
  306. // wait on future
  307. p1.set_value();
  308. f1.wait();
  309. f1.get();
  310. BOOST_CHECK( f1.valid() );
  311. }
  312. void test_shared_future_wait_for() {
  313. // future retrieved from promise is valid (if it is the first)
  314. boost::fibers::promise< int > p1;
  315. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  316. boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
  317. // wait on future
  318. BOOST_CHECK( f1.valid() );
  319. boost::fibers::future_status status = f1.wait_for( ms(300) );
  320. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  321. BOOST_CHECK( f1.valid() );
  322. status = f1.wait_for( ms(300) );
  323. BOOST_CHECK( boost::fibers::future_status::ready == status);
  324. BOOST_CHECK( f1.valid() );
  325. f1.wait();
  326. }
  327. void test_shared_future_wait_for_ref() {
  328. // future retrieved from promise is valid (if it is the first)
  329. boost::fibers::promise< int& > p1;
  330. boost::fibers::shared_future< int& > f1 = p1.get_future().share();
  331. boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
  332. // wait on future
  333. BOOST_CHECK( f1.valid() );
  334. boost::fibers::future_status status = f1.wait_for( ms(300) );
  335. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  336. BOOST_CHECK( f1.valid() );
  337. status = f1.wait_for( ms(300) );
  338. BOOST_CHECK( boost::fibers::future_status::ready == status);
  339. BOOST_CHECK( f1.valid() );
  340. f1.wait();
  341. }
  342. void test_shared_future_wait_for_void() {
  343. // future retrieved from promise is valid (if it is the first)
  344. boost::fibers::promise< void > p1;
  345. boost::fibers::shared_future< void > f1 = p1.get_future().share();
  346. boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
  347. // wait on future
  348. BOOST_CHECK( f1.valid() );
  349. boost::fibers::future_status status = f1.wait_for( ms(300) );
  350. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  351. BOOST_CHECK( f1.valid() );
  352. status = f1.wait_for( ms(300) );
  353. BOOST_CHECK( boost::fibers::future_status::ready == status);
  354. BOOST_CHECK( f1.valid() );
  355. f1.wait();
  356. }
  357. void test_shared_future_wait_until() {
  358. // future retrieved from promise is valid (if it is the first)
  359. boost::fibers::promise< int > p1;
  360. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  361. boost::fibers::fiber( boost::fibers::launch::post, fn11, std::move( p1) ).detach();
  362. // wait on future
  363. BOOST_CHECK( f1.valid() );
  364. boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
  365. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  366. BOOST_CHECK( f1.valid() );
  367. status = f1.wait_until( Clock::now() + ms(300) );
  368. BOOST_CHECK( boost::fibers::future_status::ready == status);
  369. BOOST_CHECK( f1.valid() );
  370. f1.wait();
  371. }
  372. void test_shared_future_wait_until_ref() {
  373. // future retrieved from promise is valid (if it is the first)
  374. boost::fibers::promise< int& > p1;
  375. boost::fibers::shared_future< int& > f1 = p1.get_future().share();
  376. boost::fibers::fiber( boost::fibers::launch::post, fn12, std::move( p1) ).detach();
  377. // wait on future
  378. BOOST_CHECK( f1.valid() );
  379. boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
  380. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  381. BOOST_CHECK( f1.valid() );
  382. status = f1.wait_until( Clock::now() + ms(300) );
  383. BOOST_CHECK( boost::fibers::future_status::ready == status);
  384. BOOST_CHECK( f1.valid() );
  385. f1.wait();
  386. }
  387. void test_shared_future_wait_until_void() {
  388. // future retrieved from promise is valid (if it is the first)
  389. boost::fibers::promise< void > p1;
  390. boost::fibers::shared_future< void > f1 = p1.get_future().share();
  391. boost::fibers::fiber( boost::fibers::launch::post, fn13, std::move( p1) ).detach();
  392. // wait on future
  393. BOOST_CHECK( f1.valid() );
  394. boost::fibers::future_status status = f1.wait_until( Clock::now() + ms(300) );
  395. BOOST_CHECK( boost::fibers::future_status::timeout == status);
  396. BOOST_CHECK( f1.valid() );
  397. status = f1.wait_until( Clock::now() + ms(300) );
  398. BOOST_CHECK( boost::fibers::future_status::ready == status);
  399. BOOST_CHECK( f1.valid() );
  400. f1.wait();
  401. }
  402. void test_shared_future_wait_with_fiber_1() {
  403. boost::fibers::promise< int > p1;
  404. boost::fibers::fiber( boost::fibers::launch::post, fn1, & p1, 7).detach();
  405. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  406. // wait on future
  407. BOOST_CHECK( 7 == f1.get() );
  408. }
  409. void test_shared_future_wait_with_fiber_2() {
  410. boost::fibers::fiber( boost::fibers::launch::post, fn2).join();
  411. }
  412. void test_shared_future_move() {
  413. // future retrieved from promise is valid (if it is the first)
  414. boost::fibers::promise< int > p1;
  415. boost::fibers::shared_future< int > f1 = p1.get_future().share();
  416. BOOST_CHECK( f1.valid() );
  417. // move construction
  418. boost::fibers::shared_future< int > f2( std::move( f1) );
  419. BOOST_CHECK( ! f1.valid() );
  420. BOOST_CHECK( f2.valid() );
  421. // move assignment
  422. f1 = std::move( f2);
  423. BOOST_CHECK( f1.valid() );
  424. BOOST_CHECK( ! f2.valid() );
  425. }
  426. void test_shared_future_move_move() {
  427. // future retrieved from promise is valid (if it is the first)
  428. boost::fibers::promise< A > p1;
  429. boost::fibers::shared_future< A > f1 = p1.get_future().share();
  430. BOOST_CHECK( f1.valid() );
  431. // move construction
  432. boost::fibers::shared_future< A > f2( std::move( f1) );
  433. BOOST_CHECK( ! f1.valid() );
  434. BOOST_CHECK( f2.valid() );
  435. // move assignment
  436. f1 = std::move( f2);
  437. BOOST_CHECK( f1.valid() );
  438. BOOST_CHECK( ! f2.valid() );
  439. }
  440. void test_shared_future_move_ref() {
  441. // future retrieved from promise is valid (if it is the first)
  442. boost::fibers::promise< int& > p1;
  443. boost::fibers::shared_future< int& > f1 = p1.get_future().share();
  444. BOOST_CHECK( f1.valid() );
  445. // move construction
  446. boost::fibers::shared_future< int& > f2( std::move( f1) );
  447. BOOST_CHECK( ! f1.valid() );
  448. BOOST_CHECK( f2.valid() );
  449. // move assignment
  450. f1 = std::move( f2);
  451. BOOST_CHECK( f1.valid() );
  452. BOOST_CHECK( ! f2.valid() );
  453. }
  454. void test_shared_future_move_void() {
  455. // future retrieved from promise is valid (if it is the first)
  456. boost::fibers::promise< void > p1;
  457. boost::fibers::shared_future< void > f1 = p1.get_future().share();
  458. BOOST_CHECK( f1.valid() );
  459. // move construction
  460. boost::fibers::shared_future< void > f2( std::move( f1) );
  461. BOOST_CHECK( ! f1.valid() );
  462. BOOST_CHECK( f2.valid() );
  463. // move assignment
  464. f1 = std::move( f2);
  465. BOOST_CHECK( f1.valid() );
  466. BOOST_CHECK( ! f2.valid() );
  467. }
  468. boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) {
  469. boost::unit_test_framework::test_suite* test =
  470. BOOST_TEST_SUITE("Boost.Fiber: shared_future test suite");
  471. test->add(BOOST_TEST_CASE(test_shared_future_create));
  472. test->add(BOOST_TEST_CASE(test_shared_future_create_ref));
  473. test->add(BOOST_TEST_CASE(test_shared_future_create_void));
  474. test->add(BOOST_TEST_CASE(test_shared_future_move));
  475. test->add(BOOST_TEST_CASE(test_shared_future_move_move));
  476. test->add(BOOST_TEST_CASE(test_shared_future_move_ref));
  477. test->add(BOOST_TEST_CASE(test_shared_future_move_void));
  478. test->add(BOOST_TEST_CASE(test_shared_future_get));
  479. test->add(BOOST_TEST_CASE(test_shared_future_get_move));
  480. test->add(BOOST_TEST_CASE(test_shared_future_get_ref));
  481. test->add(BOOST_TEST_CASE(test_shared_future_get_void));
  482. test->add(BOOST_TEST_CASE(test_shared_future_wait));
  483. test->add(BOOST_TEST_CASE(test_shared_future_wait_ref));
  484. test->add(BOOST_TEST_CASE(test_shared_future_wait_void));
  485. test->add(BOOST_TEST_CASE(test_shared_future_wait_for));
  486. test->add(BOOST_TEST_CASE(test_shared_future_wait_for_ref));
  487. test->add(BOOST_TEST_CASE(test_shared_future_wait_for_void));
  488. test->add(BOOST_TEST_CASE(test_shared_future_wait_until));
  489. test->add(BOOST_TEST_CASE(test_shared_future_wait_until_ref));
  490. test->add(BOOST_TEST_CASE(test_shared_future_wait_until_void));
  491. test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_1));
  492. test->add(BOOST_TEST_CASE(test_shared_future_wait_with_fiber_2));
  493. return test;
  494. }