shared_mutex.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. #ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
  2. #define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP
  3. // (C) Copyright 2006-8 Anthony Williams
  4. // (C) Copyright 2011-2012 Vicente J. Botet Escriba
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #include <boost/assert.hpp>
  10. #include <boost/detail/interlocked.hpp>
  11. #include <boost/thread/win32/thread_primitives.hpp>
  12. #include <boost/static_assert.hpp>
  13. #include <limits.h>
  14. #include <boost/thread/thread_time.hpp>
  15. #ifdef BOOST_THREAD_USES_CHRONO
  16. #include <boost/chrono/system_clocks.hpp>
  17. #include <boost/chrono/ceil.hpp>
  18. #endif
  19. #include <boost/thread/detail/delete.hpp>
  20. #include <boost/config/abi_prefix.hpp>
  21. namespace boost
  22. {
  23. class shared_mutex
  24. {
  25. private:
  26. struct state_data
  27. {
  28. unsigned shared_count:11,
  29. shared_waiting:11,
  30. exclusive:1,
  31. upgrade:1,
  32. exclusive_waiting:7,
  33. exclusive_waiting_blocked:1;
  34. friend bool operator==(state_data const& lhs,state_data const& rhs)
  35. {
  36. return *reinterpret_cast<unsigned const*>(&lhs)==*reinterpret_cast<unsigned const*>(&rhs);
  37. }
  38. };
  39. template<typename T>
  40. T interlocked_compare_exchange(T* target,T new_value,T comparand)
  41. {
  42. BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long));
  43. long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast<long*>(target),
  44. *reinterpret_cast<long*>(&new_value),
  45. *reinterpret_cast<long*>(&comparand));
  46. return *reinterpret_cast<T const*>(&res);
  47. }
  48. enum
  49. {
  50. unlock_sem = 0,
  51. exclusive_sem = 1
  52. };
  53. state_data state;
  54. detail::win32::handle semaphores[2];
  55. detail::win32::handle upgrade_sem;
  56. void release_waiters(state_data old_state)
  57. {
  58. if(old_state.exclusive_waiting)
  59. {
  60. BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0);
  61. }
  62. if(old_state.shared_waiting || old_state.exclusive_waiting)
  63. {
  64. BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0);
  65. }
  66. }
  67. public:
  68. BOOST_THREAD_NO_COPYABLE(shared_mutex)
  69. shared_mutex()
  70. {
  71. semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX);
  72. semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
  73. if (!semaphores[exclusive_sem])
  74. {
  75. detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
  76. boost::throw_exception(thread_resource_error());
  77. }
  78. upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX);
  79. if (!upgrade_sem)
  80. {
  81. detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX);
  82. detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX);
  83. boost::throw_exception(thread_resource_error());
  84. }
  85. state_data state_={0,0,0,0,0,0};
  86. state=state_;
  87. }
  88. ~shared_mutex()
  89. {
  90. detail::win32::CloseHandle(upgrade_sem);
  91. detail::win32::CloseHandle(semaphores[unlock_sem]);
  92. detail::win32::CloseHandle(semaphores[exclusive_sem]);
  93. }
  94. bool try_lock_shared()
  95. {
  96. state_data old_state=state;
  97. for(;;)
  98. {
  99. state_data new_state=old_state;
  100. if(!new_state.exclusive && !new_state.exclusive_waiting_blocked)
  101. {
  102. ++new_state.shared_count;
  103. if(!new_state.shared_count)
  104. {
  105. return false;
  106. }
  107. }
  108. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  109. if(current_state==old_state)
  110. {
  111. break;
  112. }
  113. old_state=current_state;
  114. }
  115. return !(old_state.exclusive| old_state.exclusive_waiting_blocked);
  116. }
  117. void lock_shared()
  118. {
  119. #if defined BOOST_THREAD_USES_DATETIME
  120. BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel()));
  121. #else
  122. BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now()));
  123. #endif
  124. }
  125. #if defined BOOST_THREAD_USES_DATETIME
  126. template<typename TimeDuration>
  127. bool timed_lock_shared(TimeDuration const & relative_time)
  128. {
  129. return timed_lock_shared(get_system_time()+relative_time);
  130. }
  131. bool timed_lock_shared(boost::system_time const& wait_until)
  132. {
  133. for(;;)
  134. {
  135. state_data old_state=state;
  136. for(;;)
  137. {
  138. state_data new_state=old_state;
  139. if(new_state.exclusive || new_state.exclusive_waiting_blocked)
  140. {
  141. ++new_state.shared_waiting;
  142. if(!new_state.shared_waiting)
  143. {
  144. boost::throw_exception(boost::lock_error());
  145. }
  146. }
  147. else
  148. {
  149. ++new_state.shared_count;
  150. if(!new_state.shared_count)
  151. {
  152. boost::throw_exception(boost::lock_error());
  153. }
  154. }
  155. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  156. if(current_state==old_state)
  157. {
  158. break;
  159. }
  160. old_state=current_state;
  161. }
  162. if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
  163. {
  164. return true;
  165. }
  166. unsigned long const res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until));
  167. if(res==detail::win32::timeout)
  168. {
  169. for(;;)
  170. {
  171. state_data new_state=old_state;
  172. if(new_state.exclusive || new_state.exclusive_waiting_blocked)
  173. {
  174. if(new_state.shared_waiting)
  175. {
  176. --new_state.shared_waiting;
  177. }
  178. }
  179. else
  180. {
  181. ++new_state.shared_count;
  182. if(!new_state.shared_count)
  183. {
  184. return false;
  185. }
  186. }
  187. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  188. if(current_state==old_state)
  189. {
  190. break;
  191. }
  192. old_state=current_state;
  193. }
  194. if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
  195. {
  196. return true;
  197. }
  198. return false;
  199. }
  200. BOOST_ASSERT(res==0);
  201. }
  202. }
  203. #endif
  204. #ifdef BOOST_THREAD_USES_CHRONO
  205. template <class Rep, class Period>
  206. bool try_lock_shared_for(const chrono::duration<Rep, Period>& rel_time)
  207. {
  208. return try_lock_shared_until(chrono::steady_clock::now() + rel_time);
  209. }
  210. template <class Clock, class Duration>
  211. bool try_lock_shared_until(const chrono::time_point<Clock, Duration>& t)
  212. {
  213. using namespace chrono;
  214. system_clock::time_point s_now = system_clock::now();
  215. typename Clock::time_point c_now = Clock::now();
  216. return try_lock_shared_until(s_now + ceil<system_clock::duration>(t - c_now));
  217. }
  218. template <class Duration>
  219. bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, Duration>& t)
  220. {
  221. using namespace chrono;
  222. typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
  223. return try_lock_shared_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
  224. }
  225. bool try_lock_shared_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
  226. {
  227. for(;;)
  228. {
  229. state_data old_state=state;
  230. for(;;)
  231. {
  232. state_data new_state=old_state;
  233. if(new_state.exclusive || new_state.exclusive_waiting_blocked)
  234. {
  235. ++new_state.shared_waiting;
  236. if(!new_state.shared_waiting)
  237. {
  238. boost::throw_exception(boost::lock_error());
  239. }
  240. }
  241. else
  242. {
  243. ++new_state.shared_count;
  244. if(!new_state.shared_count)
  245. {
  246. boost::throw_exception(boost::lock_error());
  247. }
  248. }
  249. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  250. if(current_state==old_state)
  251. {
  252. break;
  253. }
  254. old_state=current_state;
  255. }
  256. if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
  257. {
  258. return true;
  259. }
  260. chrono::system_clock::time_point n = chrono::system_clock::now();
  261. unsigned long res;
  262. if (tp>n) {
  263. chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-n);
  264. res=detail::win32::WaitForSingleObject(semaphores[unlock_sem],
  265. static_cast<unsigned long>(rel_time.count()));
  266. } else {
  267. res=detail::win32::timeout;
  268. }
  269. if(res==detail::win32::timeout)
  270. {
  271. for(;;)
  272. {
  273. state_data new_state=old_state;
  274. if(new_state.exclusive || new_state.exclusive_waiting_blocked)
  275. {
  276. if(new_state.shared_waiting)
  277. {
  278. --new_state.shared_waiting;
  279. }
  280. }
  281. else
  282. {
  283. ++new_state.shared_count;
  284. if(!new_state.shared_count)
  285. {
  286. return false;
  287. }
  288. }
  289. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  290. if(current_state==old_state)
  291. {
  292. break;
  293. }
  294. old_state=current_state;
  295. }
  296. if(!(old_state.exclusive| old_state.exclusive_waiting_blocked))
  297. {
  298. return true;
  299. }
  300. return false;
  301. }
  302. BOOST_ASSERT(res==0);
  303. }
  304. }
  305. #endif
  306. void unlock_shared()
  307. {
  308. state_data old_state=state;
  309. for(;;)
  310. {
  311. state_data new_state=old_state;
  312. bool const last_reader=!--new_state.shared_count;
  313. if(last_reader)
  314. {
  315. if(new_state.upgrade)
  316. {
  317. new_state.upgrade=false;
  318. new_state.exclusive=true;
  319. }
  320. else
  321. {
  322. if(new_state.exclusive_waiting)
  323. {
  324. --new_state.exclusive_waiting;
  325. new_state.exclusive_waiting_blocked=false;
  326. }
  327. new_state.shared_waiting=0;
  328. }
  329. }
  330. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  331. if(current_state==old_state)
  332. {
  333. if(last_reader)
  334. {
  335. if(old_state.upgrade)
  336. {
  337. BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0);
  338. }
  339. else
  340. {
  341. release_waiters(old_state);
  342. }
  343. }
  344. break;
  345. }
  346. old_state=current_state;
  347. }
  348. }
  349. void lock()
  350. {
  351. #if defined BOOST_THREAD_USES_DATETIME
  352. BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel()));
  353. #else
  354. BOOST_VERIFY(try_lock_until(chrono::steady_clock::now()));
  355. #endif
  356. }
  357. #if defined BOOST_THREAD_USES_DATETIME
  358. template<typename TimeDuration>
  359. bool timed_lock(TimeDuration const & relative_time)
  360. {
  361. return timed_lock(get_system_time()+relative_time);
  362. }
  363. #endif
  364. bool try_lock()
  365. {
  366. state_data old_state=state;
  367. for(;;)
  368. {
  369. state_data new_state=old_state;
  370. if(new_state.shared_count || new_state.exclusive)
  371. {
  372. return false;
  373. }
  374. else
  375. {
  376. new_state.exclusive=true;
  377. }
  378. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  379. if(current_state==old_state)
  380. {
  381. break;
  382. }
  383. old_state=current_state;
  384. }
  385. return true;
  386. }
  387. #if defined BOOST_THREAD_USES_DATETIME
  388. bool timed_lock(boost::system_time const& wait_until)
  389. {
  390. for(;;)
  391. {
  392. state_data old_state=state;
  393. for(;;)
  394. {
  395. state_data new_state=old_state;
  396. if(new_state.shared_count || new_state.exclusive)
  397. {
  398. ++new_state.exclusive_waiting;
  399. if(!new_state.exclusive_waiting)
  400. {
  401. boost::throw_exception(boost::lock_error());
  402. }
  403. new_state.exclusive_waiting_blocked=true;
  404. }
  405. else
  406. {
  407. new_state.exclusive=true;
  408. }
  409. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  410. if(current_state==old_state)
  411. {
  412. break;
  413. }
  414. old_state=current_state;
  415. }
  416. if(!old_state.shared_count && !old_state.exclusive)
  417. {
  418. return true;
  419. }
  420. #ifndef UNDER_CE
  421. const bool wait_all = true;
  422. #else
  423. const bool wait_all = false;
  424. #endif
  425. unsigned long const wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until));
  426. if(wait_res==detail::win32::timeout)
  427. {
  428. for(;;)
  429. {
  430. bool must_notify = false;
  431. state_data new_state=old_state;
  432. if(new_state.shared_count || new_state.exclusive)
  433. {
  434. if(new_state.exclusive_waiting)
  435. {
  436. if(!--new_state.exclusive_waiting)
  437. {
  438. new_state.exclusive_waiting_blocked=false;
  439. must_notify = true;
  440. }
  441. }
  442. }
  443. else
  444. {
  445. new_state.exclusive=true;
  446. }
  447. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  448. if (must_notify)
  449. {
  450. BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
  451. }
  452. if(current_state==old_state)
  453. {
  454. break;
  455. }
  456. old_state=current_state;
  457. }
  458. if(!old_state.shared_count && !old_state.exclusive)
  459. {
  460. return true;
  461. }
  462. return false;
  463. }
  464. BOOST_ASSERT(wait_res<2);
  465. }
  466. }
  467. #endif
  468. #ifdef BOOST_THREAD_USES_CHRONO
  469. template <class Rep, class Period>
  470. bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
  471. {
  472. return try_lock_until(chrono::steady_clock::now() + rel_time);
  473. }
  474. template <class Clock, class Duration>
  475. bool try_lock_until(const chrono::time_point<Clock, Duration>& t)
  476. {
  477. using namespace chrono;
  478. system_clock::time_point s_now = system_clock::now();
  479. typename Clock::time_point c_now = Clock::now();
  480. return try_lock_until(s_now + ceil<system_clock::duration>(t - c_now));
  481. }
  482. template <class Duration>
  483. bool try_lock_until(const chrono::time_point<chrono::system_clock, Duration>& t)
  484. {
  485. using namespace chrono;
  486. typedef time_point<chrono::system_clock, chrono::system_clock::duration> sys_tmpt;
  487. return try_lock_until(sys_tmpt(chrono::ceil<chrono::system_clock::duration>(t.time_since_epoch())));
  488. }
  489. bool try_lock_until(const chrono::time_point<chrono::system_clock, chrono::system_clock::duration>& tp)
  490. {
  491. for(;;)
  492. {
  493. state_data old_state=state;
  494. for(;;)
  495. {
  496. state_data new_state=old_state;
  497. if(new_state.shared_count || new_state.exclusive)
  498. {
  499. ++new_state.exclusive_waiting;
  500. if(!new_state.exclusive_waiting)
  501. {
  502. boost::throw_exception(boost::lock_error());
  503. }
  504. new_state.exclusive_waiting_blocked=true;
  505. }
  506. else
  507. {
  508. new_state.exclusive=true;
  509. }
  510. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  511. if(current_state==old_state)
  512. {
  513. break;
  514. }
  515. old_state=current_state;
  516. }
  517. if(!old_state.shared_count && !old_state.exclusive)
  518. {
  519. return true;
  520. }
  521. #ifndef UNDER_CE
  522. const bool wait_all = true;
  523. #else
  524. const bool wait_all = false;
  525. #endif
  526. chrono::system_clock::time_point n = chrono::system_clock::now();
  527. unsigned long wait_res;
  528. if (tp>n) {
  529. chrono::milliseconds rel_time= chrono::ceil<chrono::milliseconds>(tp-chrono::system_clock::now());
  530. wait_res=detail::win32::WaitForMultipleObjects(2,semaphores,wait_all,
  531. static_cast<unsigned long>(rel_time.count()));
  532. } else {
  533. wait_res=detail::win32::timeout;
  534. }
  535. if(wait_res==detail::win32::timeout)
  536. {
  537. for(;;)
  538. {
  539. bool must_notify = false;
  540. state_data new_state=old_state;
  541. if(new_state.shared_count || new_state.exclusive)
  542. {
  543. if(new_state.exclusive_waiting)
  544. {
  545. if(!--new_state.exclusive_waiting)
  546. {
  547. new_state.exclusive_waiting_blocked=false;
  548. must_notify = true;
  549. }
  550. }
  551. }
  552. else
  553. {
  554. new_state.exclusive=true;
  555. }
  556. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  557. if (must_notify)
  558. {
  559. BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0);
  560. }
  561. if(current_state==old_state)
  562. {
  563. break;
  564. }
  565. old_state=current_state;
  566. }
  567. if(!old_state.shared_count && !old_state.exclusive)
  568. {
  569. return true;
  570. }
  571. return false;
  572. }
  573. BOOST_ASSERT(wait_res<2);
  574. }
  575. }
  576. #endif
  577. void unlock()
  578. {
  579. state_data old_state=state;
  580. for(;;)
  581. {
  582. state_data new_state=old_state;
  583. new_state.exclusive=false;
  584. if(new_state.exclusive_waiting)
  585. {
  586. --new_state.exclusive_waiting;
  587. new_state.exclusive_waiting_blocked=false;
  588. }
  589. new_state.shared_waiting=0;
  590. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  591. if(current_state==old_state)
  592. {
  593. break;
  594. }
  595. old_state=current_state;
  596. }
  597. release_waiters(old_state);
  598. }
  599. void lock_upgrade()
  600. {
  601. for(;;)
  602. {
  603. state_data old_state=state;
  604. for(;;)
  605. {
  606. state_data new_state=old_state;
  607. if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
  608. {
  609. ++new_state.shared_waiting;
  610. if(!new_state.shared_waiting)
  611. {
  612. boost::throw_exception(boost::lock_error());
  613. }
  614. }
  615. else
  616. {
  617. ++new_state.shared_count;
  618. if(!new_state.shared_count)
  619. {
  620. boost::throw_exception(boost::lock_error());
  621. }
  622. new_state.upgrade=true;
  623. }
  624. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  625. if(current_state==old_state)
  626. {
  627. break;
  628. }
  629. old_state=current_state;
  630. }
  631. if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade))
  632. {
  633. return;
  634. }
  635. BOOST_VERIFY(!detail::win32::WaitForSingleObject(semaphores[unlock_sem],detail::win32::infinite));
  636. }
  637. }
  638. bool try_lock_upgrade()
  639. {
  640. state_data old_state=state;
  641. for(;;)
  642. {
  643. state_data new_state=old_state;
  644. if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade)
  645. {
  646. return false;
  647. }
  648. else
  649. {
  650. ++new_state.shared_count;
  651. if(!new_state.shared_count)
  652. {
  653. return false;
  654. }
  655. new_state.upgrade=true;
  656. }
  657. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  658. if(current_state==old_state)
  659. {
  660. break;
  661. }
  662. old_state=current_state;
  663. }
  664. return true;
  665. }
  666. void unlock_upgrade()
  667. {
  668. state_data old_state=state;
  669. for(;;)
  670. {
  671. state_data new_state=old_state;
  672. new_state.upgrade=false;
  673. bool const last_reader=!--new_state.shared_count;
  674. if(last_reader)
  675. {
  676. if(new_state.exclusive_waiting)
  677. {
  678. --new_state.exclusive_waiting;
  679. new_state.exclusive_waiting_blocked=false;
  680. }
  681. new_state.shared_waiting=0;
  682. }
  683. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  684. if(current_state==old_state)
  685. {
  686. if(last_reader)
  687. {
  688. release_waiters(old_state);
  689. }
  690. // #7720
  691. //else {
  692. // release_waiters(old_state);
  693. //}
  694. break;
  695. }
  696. old_state=current_state;
  697. }
  698. }
  699. void unlock_upgrade_and_lock()
  700. {
  701. state_data old_state=state;
  702. for(;;)
  703. {
  704. state_data new_state=old_state;
  705. bool const last_reader=!--new_state.shared_count;
  706. if(last_reader)
  707. {
  708. new_state.upgrade=false;
  709. new_state.exclusive=true;
  710. }
  711. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  712. if(current_state==old_state)
  713. {
  714. if(!last_reader)
  715. {
  716. BOOST_VERIFY(!detail::win32::WaitForSingleObject(upgrade_sem,detail::win32::infinite));
  717. }
  718. break;
  719. }
  720. old_state=current_state;
  721. }
  722. }
  723. void unlock_and_lock_upgrade()
  724. {
  725. state_data old_state=state;
  726. for(;;)
  727. {
  728. state_data new_state=old_state;
  729. new_state.exclusive=false;
  730. new_state.upgrade=true;
  731. ++new_state.shared_count;
  732. if(new_state.exclusive_waiting)
  733. {
  734. --new_state.exclusive_waiting;
  735. new_state.exclusive_waiting_blocked=false;
  736. }
  737. new_state.shared_waiting=0;
  738. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  739. if(current_state==old_state)
  740. {
  741. break;
  742. }
  743. old_state=current_state;
  744. }
  745. release_waiters(old_state);
  746. }
  747. // bool try_unlock_upgrade_and_lock()
  748. // {
  749. // return false;
  750. // }
  751. //#ifdef BOOST_THREAD_USES_CHRONO
  752. // template <class Rep, class Period>
  753. // bool
  754. // try_unlock_upgrade_and_lock_for(
  755. // const chrono::duration<Rep, Period>& rel_time)
  756. // {
  757. // return try_unlock_upgrade_and_lock_until(
  758. // chrono::steady_clock::now() + rel_time);
  759. // }
  760. // template <class Clock, class Duration>
  761. // bool
  762. // try_unlock_upgrade_and_lock_until(
  763. // const chrono::time_point<Clock, Duration>& abs_time)
  764. // {
  765. // return false;
  766. // }
  767. //#endif
  768. void unlock_and_lock_shared()
  769. {
  770. state_data old_state=state;
  771. for(;;)
  772. {
  773. state_data new_state=old_state;
  774. new_state.exclusive=false;
  775. ++new_state.shared_count;
  776. if(new_state.exclusive_waiting)
  777. {
  778. --new_state.exclusive_waiting;
  779. new_state.exclusive_waiting_blocked=false;
  780. }
  781. new_state.shared_waiting=0;
  782. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  783. if(current_state==old_state)
  784. {
  785. break;
  786. }
  787. old_state=current_state;
  788. }
  789. release_waiters(old_state);
  790. }
  791. void unlock_upgrade_and_lock_shared()
  792. {
  793. state_data old_state=state;
  794. for(;;)
  795. {
  796. state_data new_state=old_state;
  797. new_state.upgrade=false;
  798. if(new_state.exclusive_waiting)
  799. {
  800. --new_state.exclusive_waiting;
  801. new_state.exclusive_waiting_blocked=false;
  802. }
  803. new_state.shared_waiting=0;
  804. state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state);
  805. if(current_state==old_state)
  806. {
  807. break;
  808. }
  809. old_state=current_state;
  810. }
  811. release_waiters(old_state);
  812. }
  813. };
  814. typedef shared_mutex upgrade_mutex;
  815. }
  816. #include <boost/config/abi_suffix.hpp>
  817. #endif