shared_mutex.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
  2. #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
  3. // shared_mutex.hpp
  4. //
  5. // Copyright Howard Hinnant 2007-2010.
  6. // Copyright Vicente J. Botet Escriba 2012.
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See
  9. // accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. /*
  12. <shared_mutex> synopsis
  13. namespace boost
  14. {
  15. namespace thread_v2
  16. {
  17. class shared_mutex
  18. {
  19. public:
  20. shared_mutex();
  21. ~shared_mutex();
  22. shared_mutex(const shared_mutex&) = delete;
  23. shared_mutex& operator=(const shared_mutex&) = delete;
  24. // Exclusive ownership
  25. void lock();
  26. bool try_lock();
  27. template <class Rep, class Period>
  28. bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
  29. template <class Clock, class Duration>
  30. bool
  31. try_lock_until(
  32. const boost::chrono::time_point<Clock, Duration>& abs_time);
  33. void unlock();
  34. // Shared ownership
  35. void lock_shared();
  36. bool try_lock_shared();
  37. template <class Rep, class Period>
  38. bool
  39. try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
  40. template <class Clock, class Duration>
  41. bool
  42. try_lock_shared_until(
  43. const boost::chrono::time_point<Clock, Duration>& abs_time);
  44. void unlock_shared();
  45. };
  46. class upgrade_mutex
  47. {
  48. public:
  49. upgrade_mutex();
  50. ~upgrade_mutex();
  51. upgrade_mutex(const upgrade_mutex&) = delete;
  52. upgrade_mutex& operator=(const upgrade_mutex&) = delete;
  53. // Exclusive ownership
  54. void lock();
  55. bool try_lock();
  56. template <class Rep, class Period>
  57. bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
  58. template <class Clock, class Duration>
  59. bool
  60. try_lock_until(
  61. const boost::chrono::time_point<Clock, Duration>& abs_time);
  62. void unlock();
  63. // Shared ownership
  64. void lock_shared();
  65. bool try_lock_shared();
  66. template <class Rep, class Period>
  67. bool
  68. try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
  69. template <class Clock, class Duration>
  70. bool
  71. try_lock_shared_until(
  72. const boost::chrono::time_point<Clock, Duration>& abs_time);
  73. void unlock_shared();
  74. // Upgrade ownership
  75. void lock_upgrade();
  76. bool try_lock_upgrade();
  77. template <class Rep, class Period>
  78. bool
  79. try_lock_upgrade_for(
  80. const boost::chrono::duration<Rep, Period>& rel_time);
  81. template <class Clock, class Duration>
  82. bool
  83. try_lock_upgrade_until(
  84. const boost::chrono::time_point<Clock, Duration>& abs_time);
  85. void unlock_upgrade();
  86. // Shared <-> Exclusive
  87. bool try_unlock_shared_and_lock();
  88. template <class Rep, class Period>
  89. bool
  90. try_unlock_shared_and_lock_for(
  91. const boost::chrono::duration<Rep, Period>& rel_time);
  92. template <class Clock, class Duration>
  93. bool
  94. try_unlock_shared_and_lock_until(
  95. const boost::chrono::time_point<Clock, Duration>& abs_time);
  96. void unlock_and_lock_shared();
  97. // Shared <-> Upgrade
  98. bool try_unlock_shared_and_lock_upgrade();
  99. template <class Rep, class Period>
  100. bool
  101. try_unlock_shared_and_lock_upgrade_for(
  102. const boost::chrono::duration<Rep, Period>& rel_time);
  103. template <class Clock, class Duration>
  104. bool
  105. try_unlock_shared_and_lock_upgrade_until(
  106. const boost::chrono::time_point<Clock, Duration>& abs_time);
  107. void unlock_upgrade_and_lock_shared();
  108. // Upgrade <-> Exclusive
  109. void unlock_upgrade_and_lock();
  110. bool try_unlock_upgrade_and_lock();
  111. template <class Rep, class Period>
  112. bool
  113. try_unlock_upgrade_and_lock_for(
  114. const boost::chrono::duration<Rep, Period>& rel_time);
  115. template <class Clock, class Duration>
  116. bool
  117. try_unlock_upgrade_and_lock_until(
  118. const boost::chrono::time_point<Clock, Duration>& abs_time);
  119. void unlock_and_lock_upgrade();
  120. };
  121. } // thread_v2
  122. } // boost
  123. */
  124. #include <boost/thread/detail/config.hpp>
  125. #include <boost/thread/mutex.hpp>
  126. #include <boost/thread/condition_variable.hpp>
  127. #include <boost/thread/mutex.hpp>
  128. #include <boost/chrono.hpp>
  129. #include <climits>
  130. #include <boost/system/system_error.hpp>
  131. #define BOOST_THREAD_INLINE inline
  132. namespace boost {
  133. namespace thread_v2 {
  134. class shared_mutex
  135. {
  136. typedef ::boost::mutex mutex_t;
  137. typedef ::boost::condition_variable cond_t;
  138. typedef unsigned count_t;
  139. mutex_t mut_;
  140. cond_t gate1_;
  141. cond_t gate2_;
  142. count_t state_;
  143. static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
  144. static const count_t n_readers_ = ~write_entered_;
  145. public:
  146. BOOST_THREAD_INLINE shared_mutex();
  147. BOOST_THREAD_INLINE ~shared_mutex();
  148. #ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS
  149. shared_mutex(shared_mutex const&) = delete;
  150. shared_mutex& operator=(shared_mutex const&) = delete;
  151. #else // BOOST_NO_CXX11_DELETED_FUNCTIONS
  152. private:
  153. shared_mutex(shared_mutex const&);
  154. shared_mutex& operator=(shared_mutex const&);
  155. public:
  156. #endif // BOOST_NO_CXX11_DELETED_FUNCTIONS
  157. // Exclusive ownership
  158. BOOST_THREAD_INLINE void lock();
  159. BOOST_THREAD_INLINE bool try_lock();
  160. template <class Rep, class Period>
  161. bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
  162. {
  163. return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
  164. }
  165. template <class Clock, class Duration>
  166. bool
  167. try_lock_until(
  168. const boost::chrono::time_point<Clock, Duration>& abs_time);
  169. BOOST_THREAD_INLINE void unlock();
  170. // Shared ownership
  171. BOOST_THREAD_INLINE void lock_shared();
  172. BOOST_THREAD_INLINE bool try_lock_shared();
  173. template <class Rep, class Period>
  174. bool
  175. try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
  176. {
  177. return try_lock_shared_until(boost::chrono::steady_clock::now() +
  178. rel_time);
  179. }
  180. template <class Clock, class Duration>
  181. bool
  182. try_lock_shared_until(
  183. const boost::chrono::time_point<Clock, Duration>& abs_time);
  184. BOOST_THREAD_INLINE void unlock_shared();
  185. #if defined BOOST_THREAD_USES_DATETIME
  186. bool timed_lock(system_time const& timeout);
  187. template<typename TimeDuration>
  188. bool timed_lock(TimeDuration const & relative_time)
  189. {
  190. return timed_lock(get_system_time()+relative_time);
  191. }
  192. bool timed_lock_shared(system_time const& timeout);
  193. template<typename TimeDuration>
  194. bool timed_lock_shared(TimeDuration const & relative_time)
  195. {
  196. return timed_lock_shared(get_system_time()+relative_time);
  197. }
  198. #endif
  199. };
  200. template <class Clock, class Duration>
  201. bool
  202. shared_mutex::try_lock_until(
  203. const boost::chrono::time_point<Clock, Duration>& abs_time)
  204. {
  205. boost::unique_lock<mutex_t> lk(mut_);
  206. if (state_ & write_entered_)
  207. {
  208. while (true)
  209. {
  210. boost::cv_status status = gate1_.wait_until(lk, abs_time);
  211. if ((state_ & write_entered_) == 0)
  212. break;
  213. if (status == boost::cv_status::timeout)
  214. return false;
  215. }
  216. }
  217. state_ |= write_entered_;
  218. if (state_ & n_readers_)
  219. {
  220. while (true)
  221. {
  222. boost::cv_status status = gate2_.wait_until(lk, abs_time);
  223. if ((state_ & n_readers_) == 0)
  224. break;
  225. if (status == boost::cv_status::timeout)
  226. {
  227. state_ &= ~write_entered_;
  228. return false;
  229. }
  230. }
  231. }
  232. return true;
  233. }
  234. template <class Clock, class Duration>
  235. bool
  236. shared_mutex::try_lock_shared_until(
  237. const boost::chrono::time_point<Clock, Duration>& abs_time)
  238. {
  239. boost::unique_lock<mutex_t> lk(mut_);
  240. if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
  241. {
  242. while (true)
  243. {
  244. boost::cv_status status = gate1_.wait_until(lk, abs_time);
  245. if ((state_ & write_entered_) == 0 &&
  246. (state_ & n_readers_) < n_readers_)
  247. break;
  248. if (status == boost::cv_status::timeout)
  249. return false;
  250. }
  251. }
  252. count_t num_readers = (state_ & n_readers_) + 1;
  253. state_ &= ~n_readers_;
  254. state_ |= num_readers;
  255. return true;
  256. }
  257. #if defined BOOST_THREAD_USES_DATETIME
  258. bool shared_mutex::timed_lock(system_time const& abs_time)
  259. {
  260. boost::unique_lock<mutex_t> lk(mut_);
  261. if (state_ & write_entered_)
  262. {
  263. while (true)
  264. {
  265. bool status = gate1_.timed_wait(lk, abs_time);
  266. if ((state_ & write_entered_) == 0)
  267. break;
  268. if (!status)
  269. return false;
  270. }
  271. }
  272. state_ |= write_entered_;
  273. if (state_ & n_readers_)
  274. {
  275. while (true)
  276. {
  277. bool status = gate2_.timed_wait(lk, abs_time);
  278. if ((state_ & n_readers_) == 0)
  279. break;
  280. if (!status)
  281. {
  282. state_ &= ~write_entered_;
  283. return false;
  284. }
  285. }
  286. }
  287. return true;
  288. }
  289. bool shared_mutex::timed_lock_shared(system_time const& abs_time)
  290. {
  291. boost::unique_lock<mutex_t> lk(mut_);
  292. if (state_ & write_entered_)
  293. {
  294. while (true)
  295. {
  296. bool status = gate1_.timed_wait(lk, abs_time);
  297. if ((state_ & write_entered_) == 0)
  298. break;
  299. if (!status )
  300. return false;
  301. }
  302. }
  303. state_ |= write_entered_;
  304. if (state_ & n_readers_)
  305. {
  306. while (true)
  307. {
  308. bool status = gate2_.timed_wait(lk, abs_time);
  309. if ((state_ & n_readers_) == 0)
  310. break;
  311. if (!status)
  312. {
  313. state_ &= ~write_entered_;
  314. return false;
  315. }
  316. }
  317. }
  318. return true;
  319. }
  320. #endif
  321. class upgrade_mutex
  322. {
  323. typedef boost::mutex mutex_t;
  324. typedef boost::condition_variable cond_t;
  325. typedef unsigned count_t;
  326. mutex_t mut_;
  327. cond_t gate1_;
  328. cond_t gate2_;
  329. count_t state_;
  330. static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
  331. static const unsigned upgradable_entered_ = write_entered_ >> 1;
  332. static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
  333. public:
  334. BOOST_THREAD_INLINE upgrade_mutex();
  335. BOOST_THREAD_INLINE ~upgrade_mutex();
  336. #ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS
  337. upgrade_mutex(const upgrade_mutex&) = delete;
  338. upgrade_mutex& operator=(const upgrade_mutex&) = delete;
  339. #else // BOOST_CXX11_NO_DELETED_FUNCTIONS
  340. private:
  341. upgrade_mutex(const upgrade_mutex&);
  342. upgrade_mutex& operator=(const upgrade_mutex&);
  343. public:
  344. #endif // BOOST_CXX11_NO_DELETED_FUNCTIONS
  345. // Exclusive ownership
  346. BOOST_THREAD_INLINE void lock();
  347. BOOST_THREAD_INLINE bool try_lock();
  348. template <class Rep, class Period>
  349. bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
  350. {
  351. return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
  352. }
  353. template <class Clock, class Duration>
  354. bool
  355. try_lock_until(
  356. const boost::chrono::time_point<Clock, Duration>& abs_time);
  357. BOOST_THREAD_INLINE void unlock();
  358. // Shared ownership
  359. BOOST_THREAD_INLINE void lock_shared();
  360. BOOST_THREAD_INLINE bool try_lock_shared();
  361. template <class Rep, class Period>
  362. bool
  363. try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
  364. {
  365. return try_lock_shared_until(boost::chrono::steady_clock::now() +
  366. rel_time);
  367. }
  368. template <class Clock, class Duration>
  369. bool
  370. try_lock_shared_until(
  371. const boost::chrono::time_point<Clock, Duration>& abs_time);
  372. BOOST_THREAD_INLINE void unlock_shared();
  373. // Upgrade ownership
  374. BOOST_THREAD_INLINE void lock_upgrade();
  375. BOOST_THREAD_INLINE bool try_lock_upgrade();
  376. template <class Rep, class Period>
  377. bool
  378. try_lock_upgrade_for(
  379. const boost::chrono::duration<Rep, Period>& rel_time)
  380. {
  381. return try_lock_upgrade_until(boost::chrono::steady_clock::now() +
  382. rel_time);
  383. }
  384. template <class Clock, class Duration>
  385. bool
  386. try_lock_upgrade_until(
  387. const boost::chrono::time_point<Clock, Duration>& abs_time);
  388. BOOST_THREAD_INLINE void unlock_upgrade();
  389. // Shared <-> Exclusive
  390. BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
  391. template <class Rep, class Period>
  392. bool
  393. try_unlock_shared_and_lock_for(
  394. const boost::chrono::duration<Rep, Period>& rel_time)
  395. {
  396. return try_unlock_shared_and_lock_until(
  397. boost::chrono::steady_clock::now() + rel_time);
  398. }
  399. template <class Clock, class Duration>
  400. bool
  401. try_unlock_shared_and_lock_until(
  402. const boost::chrono::time_point<Clock, Duration>& abs_time);
  403. BOOST_THREAD_INLINE void unlock_and_lock_shared();
  404. // Shared <-> Upgrade
  405. BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
  406. template <class Rep, class Period>
  407. bool
  408. try_unlock_shared_and_lock_upgrade_for(
  409. const boost::chrono::duration<Rep, Period>& rel_time)
  410. {
  411. return try_unlock_shared_and_lock_upgrade_until(
  412. boost::chrono::steady_clock::now() + rel_time);
  413. }
  414. template <class Clock, class Duration>
  415. bool
  416. try_unlock_shared_and_lock_upgrade_until(
  417. const boost::chrono::time_point<Clock, Duration>& abs_time);
  418. BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared();
  419. // Upgrade <-> Exclusive
  420. BOOST_THREAD_INLINE void unlock_upgrade_and_lock();
  421. BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock();
  422. template <class Rep, class Period>
  423. bool
  424. try_unlock_upgrade_and_lock_for(
  425. const boost::chrono::duration<Rep, Period>& rel_time)
  426. {
  427. return try_unlock_upgrade_and_lock_until(
  428. boost::chrono::steady_clock::now() + rel_time);
  429. }
  430. template <class Clock, class Duration>
  431. bool
  432. try_unlock_upgrade_and_lock_until(
  433. const boost::chrono::time_point<Clock, Duration>& abs_time);
  434. BOOST_THREAD_INLINE void unlock_and_lock_upgrade();
  435. #if defined BOOST_THREAD_USES_DATETIME
  436. inline bool timed_lock(system_time const& abs_time);
  437. template<typename TimeDuration>
  438. bool timed_lock(TimeDuration const & relative_time)
  439. {
  440. return timed_lock(get_system_time()+relative_time);
  441. }
  442. inline bool timed_lock_shared(system_time const& abs_time);
  443. template<typename TimeDuration>
  444. bool timed_lock_shared(TimeDuration const & relative_time)
  445. {
  446. return timed_lock_shared(get_system_time()+relative_time);
  447. }
  448. inline bool timed_lock_upgrade(system_time const& abs_time);
  449. template<typename TimeDuration>
  450. bool timed_lock_upgrade(TimeDuration const & relative_time)
  451. {
  452. return timed_lock_upgrade(get_system_time()+relative_time);
  453. }
  454. #endif
  455. };
  456. template <class Clock, class Duration>
  457. bool
  458. upgrade_mutex::try_lock_until(
  459. const boost::chrono::time_point<Clock, Duration>& abs_time)
  460. {
  461. boost::unique_lock<mutex_t> lk(mut_);
  462. if (state_ & (write_entered_ | upgradable_entered_))
  463. {
  464. while (true)
  465. {
  466. boost::cv_status status = gate1_.wait_until(lk, abs_time);
  467. if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
  468. break;
  469. if (status == boost::cv_status::timeout)
  470. return false;
  471. }
  472. }
  473. state_ |= write_entered_;
  474. if (state_ & n_readers_)
  475. {
  476. while (true)
  477. {
  478. boost::cv_status status = gate2_.wait_until(lk, abs_time);
  479. if ((state_ & n_readers_) == 0)
  480. break;
  481. if (status == boost::cv_status::timeout)
  482. {
  483. state_ &= ~write_entered_;
  484. return false;
  485. }
  486. }
  487. }
  488. return true;
  489. }
  490. template <class Clock, class Duration>
  491. bool
  492. upgrade_mutex::try_lock_shared_until(
  493. const boost::chrono::time_point<Clock, Duration>& abs_time)
  494. {
  495. boost::unique_lock<mutex_t> lk(mut_);
  496. if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
  497. {
  498. while (true)
  499. {
  500. boost::cv_status status = gate1_.wait_until(lk, abs_time);
  501. if ((state_ & write_entered_) == 0 &&
  502. (state_ & n_readers_) < n_readers_)
  503. break;
  504. if (status == boost::cv_status::timeout)
  505. return false;
  506. }
  507. }
  508. count_t num_readers = (state_ & n_readers_) + 1;
  509. state_ &= ~n_readers_;
  510. state_ |= num_readers;
  511. return true;
  512. }
  513. template <class Clock, class Duration>
  514. bool
  515. upgrade_mutex::try_lock_upgrade_until(
  516. const boost::chrono::time_point<Clock, Duration>& abs_time)
  517. {
  518. boost::unique_lock<mutex_t> lk(mut_);
  519. if ((state_ & (write_entered_ | upgradable_entered_)) ||
  520. (state_ & n_readers_) == n_readers_)
  521. {
  522. while (true)
  523. {
  524. boost::cv_status status = gate1_.wait_until(lk, abs_time);
  525. if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
  526. (state_ & n_readers_) < n_readers_)
  527. break;
  528. if (status == boost::cv_status::timeout)
  529. return false;
  530. }
  531. }
  532. count_t num_readers = (state_ & n_readers_) + 1;
  533. state_ &= ~n_readers_;
  534. state_ |= upgradable_entered_ | num_readers;
  535. return true;
  536. }
  537. #if defined BOOST_THREAD_USES_DATETIME
  538. bool upgrade_mutex::timed_lock(system_time const& abs_time)
  539. {
  540. boost::unique_lock<mutex_t> lk(mut_);
  541. if (state_ & (write_entered_ | upgradable_entered_))
  542. {
  543. while (true)
  544. {
  545. bool status = gate1_.timed_wait(lk, abs_time);
  546. if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
  547. break;
  548. if (!status)
  549. return false;
  550. }
  551. }
  552. state_ |= write_entered_;
  553. if (state_ & n_readers_)
  554. {
  555. while (true)
  556. {
  557. bool status = gate2_.timed_wait(lk, abs_time);
  558. if ((state_ & n_readers_) == 0)
  559. break;
  560. if (!status)
  561. {
  562. state_ &= ~write_entered_;
  563. return false;
  564. }
  565. }
  566. }
  567. return true;
  568. }
  569. bool upgrade_mutex::timed_lock_shared(system_time const& abs_time)
  570. {
  571. boost::unique_lock<mutex_t> lk(mut_);
  572. if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
  573. {
  574. while (true)
  575. {
  576. bool status = gate1_.timed_wait(lk, abs_time);
  577. if ((state_ & write_entered_) == 0 &&
  578. (state_ & n_readers_) < n_readers_)
  579. break;
  580. if (!status)
  581. return false;
  582. }
  583. }
  584. count_t num_readers = (state_ & n_readers_) + 1;
  585. state_ &= ~n_readers_;
  586. state_ |= num_readers;
  587. return true;
  588. }
  589. bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time)
  590. {
  591. boost::unique_lock<mutex_t> lk(mut_);
  592. if ((state_ & (write_entered_ | upgradable_entered_)) ||
  593. (state_ & n_readers_) == n_readers_)
  594. {
  595. while (true)
  596. {
  597. bool status = gate1_.timed_wait(lk, abs_time);
  598. if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
  599. (state_ & n_readers_) < n_readers_)
  600. break;
  601. if (!status)
  602. return false;
  603. }
  604. }
  605. count_t num_readers = (state_ & n_readers_) + 1;
  606. state_ &= ~n_readers_;
  607. state_ |= upgradable_entered_ | num_readers;
  608. return true;
  609. }
  610. #endif
  611. template <class Clock, class Duration>
  612. bool
  613. upgrade_mutex::try_unlock_shared_and_lock_until(
  614. const boost::chrono::time_point<Clock, Duration>& abs_time)
  615. {
  616. boost::unique_lock<mutex_t> lk(mut_);
  617. if (state_ != 1)
  618. {
  619. while (true)
  620. {
  621. boost::cv_status status = gate2_.wait_until(lk, abs_time);
  622. if (state_ == 1)
  623. break;
  624. if (status == boost::cv_status::timeout)
  625. return false;
  626. }
  627. }
  628. state_ = write_entered_;
  629. return true;
  630. }
  631. template <class Clock, class Duration>
  632. bool
  633. upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
  634. const boost::chrono::time_point<Clock, Duration>& abs_time)
  635. {
  636. boost::unique_lock<mutex_t> lk(mut_);
  637. if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
  638. {
  639. while (true)
  640. {
  641. boost::cv_status status = gate2_.wait_until(lk, abs_time);
  642. if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
  643. break;
  644. if (status == boost::cv_status::timeout)
  645. return false;
  646. }
  647. }
  648. state_ |= upgradable_entered_;
  649. return true;
  650. }
  651. template <class Clock, class Duration>
  652. bool
  653. upgrade_mutex::try_unlock_upgrade_and_lock_until(
  654. const boost::chrono::time_point<Clock, Duration>& abs_time)
  655. {
  656. boost::unique_lock<mutex_t> lk(mut_);
  657. if ((state_ & n_readers_) != 1)
  658. {
  659. while (true)
  660. {
  661. boost::cv_status status = gate2_.wait_until(lk, abs_time);
  662. if ((state_ & n_readers_) == 1)
  663. break;
  664. if (status == boost::cv_status::timeout)
  665. return false;
  666. }
  667. }
  668. state_ = write_entered_;
  669. return true;
  670. }
  671. //////
  672. // shared_mutex
  673. shared_mutex::shared_mutex()
  674. : state_(0)
  675. {
  676. }
  677. shared_mutex::~shared_mutex()
  678. {
  679. boost::lock_guard<mutex_t> _(mut_);
  680. }
  681. // Exclusive ownership
  682. void
  683. shared_mutex::lock()
  684. {
  685. boost::unique_lock<mutex_t> lk(mut_);
  686. while (state_ & write_entered_)
  687. gate1_.wait(lk);
  688. state_ |= write_entered_;
  689. while (state_ & n_readers_)
  690. gate2_.wait(lk);
  691. }
  692. bool
  693. shared_mutex::try_lock()
  694. {
  695. boost::unique_lock<mutex_t> lk(mut_);
  696. if (state_ == 0)
  697. {
  698. state_ = write_entered_;
  699. return true;
  700. }
  701. return false;
  702. }
  703. void
  704. shared_mutex::unlock()
  705. {
  706. boost::lock_guard<mutex_t> _(mut_);
  707. state_ = 0;
  708. gate1_.notify_all();
  709. }
  710. // Shared ownership
  711. void
  712. shared_mutex::lock_shared()
  713. {
  714. boost::unique_lock<mutex_t> lk(mut_);
  715. while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
  716. gate1_.wait(lk);
  717. count_t num_readers = (state_ & n_readers_) + 1;
  718. state_ &= ~n_readers_;
  719. state_ |= num_readers;
  720. }
  721. bool
  722. shared_mutex::try_lock_shared()
  723. {
  724. boost::unique_lock<mutex_t> lk(mut_);
  725. count_t num_readers = state_ & n_readers_;
  726. if (!(state_ & write_entered_) && num_readers != n_readers_)
  727. {
  728. ++num_readers;
  729. state_ &= ~n_readers_;
  730. state_ |= num_readers;
  731. return true;
  732. }
  733. return false;
  734. }
  735. void
  736. shared_mutex::unlock_shared()
  737. {
  738. boost::lock_guard<mutex_t> _(mut_);
  739. count_t num_readers = (state_ & n_readers_) - 1;
  740. state_ &= ~n_readers_;
  741. state_ |= num_readers;
  742. if (state_ & write_entered_)
  743. {
  744. if (num_readers == 0)
  745. gate2_.notify_one();
  746. }
  747. else
  748. {
  749. if (num_readers == n_readers_ - 1)
  750. gate1_.notify_one();
  751. }
  752. }
  753. // upgrade_mutex
  754. upgrade_mutex::upgrade_mutex()
  755. : gate1_(),
  756. gate2_(),
  757. state_(0)
  758. {
  759. }
  760. upgrade_mutex::~upgrade_mutex()
  761. {
  762. boost::lock_guard<mutex_t> _(mut_);
  763. }
  764. // Exclusive ownership
  765. void
  766. upgrade_mutex::lock()
  767. {
  768. boost::unique_lock<mutex_t> lk(mut_);
  769. while (state_ & (write_entered_ | upgradable_entered_))
  770. gate1_.wait(lk);
  771. state_ |= write_entered_;
  772. while (state_ & n_readers_)
  773. gate2_.wait(lk);
  774. }
  775. bool
  776. upgrade_mutex::try_lock()
  777. {
  778. boost::unique_lock<mutex_t> lk(mut_);
  779. if (state_ == 0)
  780. {
  781. state_ = write_entered_;
  782. return true;
  783. }
  784. return false;
  785. }
  786. void
  787. upgrade_mutex::unlock()
  788. {
  789. boost::lock_guard<mutex_t> _(mut_);
  790. state_ = 0;
  791. gate1_.notify_all();
  792. }
  793. // Shared ownership
  794. void
  795. upgrade_mutex::lock_shared()
  796. {
  797. boost::unique_lock<mutex_t> lk(mut_);
  798. while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
  799. gate1_.wait(lk);
  800. count_t num_readers = (state_ & n_readers_) + 1;
  801. state_ &= ~n_readers_;
  802. state_ |= num_readers;
  803. }
  804. bool
  805. upgrade_mutex::try_lock_shared()
  806. {
  807. boost::unique_lock<mutex_t> lk(mut_);
  808. count_t num_readers = state_ & n_readers_;
  809. if (!(state_ & write_entered_) && num_readers != n_readers_)
  810. {
  811. ++num_readers;
  812. state_ &= ~n_readers_;
  813. state_ |= num_readers;
  814. return true;
  815. }
  816. return false;
  817. }
  818. void
  819. upgrade_mutex::unlock_shared()
  820. {
  821. boost::lock_guard<mutex_t> _(mut_);
  822. count_t num_readers = (state_ & n_readers_) - 1;
  823. state_ &= ~n_readers_;
  824. state_ |= num_readers;
  825. if (state_ & write_entered_)
  826. {
  827. if (num_readers == 0)
  828. gate2_.notify_one();
  829. }
  830. else
  831. {
  832. if (num_readers == n_readers_ - 1)
  833. gate1_.notify_one();
  834. }
  835. }
  836. // Upgrade ownership
  837. void
  838. upgrade_mutex::lock_upgrade()
  839. {
  840. boost::unique_lock<mutex_t> lk(mut_);
  841. while ((state_ & (write_entered_ | upgradable_entered_)) ||
  842. (state_ & n_readers_) == n_readers_)
  843. gate1_.wait(lk);
  844. count_t num_readers = (state_ & n_readers_) + 1;
  845. state_ &= ~n_readers_;
  846. state_ |= upgradable_entered_ | num_readers;
  847. }
  848. bool
  849. upgrade_mutex::try_lock_upgrade()
  850. {
  851. boost::unique_lock<mutex_t> lk(mut_);
  852. count_t num_readers = state_ & n_readers_;
  853. if (!(state_ & (write_entered_ | upgradable_entered_))
  854. && num_readers != n_readers_)
  855. {
  856. ++num_readers;
  857. state_ &= ~n_readers_;
  858. state_ |= upgradable_entered_ | num_readers;
  859. return true;
  860. }
  861. return false;
  862. }
  863. void
  864. upgrade_mutex::unlock_upgrade()
  865. {
  866. {
  867. boost::lock_guard<mutex_t> _(mut_);
  868. count_t num_readers = (state_ & n_readers_) - 1;
  869. state_ &= ~(upgradable_entered_ | n_readers_);
  870. state_ |= num_readers;
  871. }
  872. gate1_.notify_all();
  873. }
  874. // Shared <-> Exclusive
  875. bool
  876. upgrade_mutex::try_unlock_shared_and_lock()
  877. {
  878. boost::unique_lock<mutex_t> lk(mut_);
  879. if (state_ == 1)
  880. {
  881. state_ = write_entered_;
  882. return true;
  883. }
  884. return false;
  885. }
  886. void
  887. upgrade_mutex::unlock_and_lock_shared()
  888. {
  889. {
  890. boost::lock_guard<mutex_t> _(mut_);
  891. state_ = 1;
  892. }
  893. gate1_.notify_all();
  894. }
  895. // Shared <-> Upgrade
  896. bool
  897. upgrade_mutex::try_unlock_shared_and_lock_upgrade()
  898. {
  899. boost::unique_lock<mutex_t> lk(mut_);
  900. if (!(state_ & (write_entered_ | upgradable_entered_)))
  901. {
  902. state_ |= upgradable_entered_;
  903. return true;
  904. }
  905. return false;
  906. }
  907. void
  908. upgrade_mutex::unlock_upgrade_and_lock_shared()
  909. {
  910. {
  911. boost::lock_guard<mutex_t> _(mut_);
  912. state_ &= ~upgradable_entered_;
  913. }
  914. gate1_.notify_all();
  915. }
  916. // Upgrade <-> Exclusive
  917. void
  918. upgrade_mutex::unlock_upgrade_and_lock()
  919. {
  920. boost::unique_lock<mutex_t> lk(mut_);
  921. count_t num_readers = (state_ & n_readers_) - 1;
  922. state_ &= ~(upgradable_entered_ | n_readers_);
  923. state_ |= write_entered_ | num_readers;
  924. while (state_ & n_readers_)
  925. gate2_.wait(lk);
  926. }
  927. bool
  928. upgrade_mutex::try_unlock_upgrade_and_lock()
  929. {
  930. boost::unique_lock<mutex_t> lk(mut_);
  931. if (state_ == (upgradable_entered_ | 1))
  932. {
  933. state_ = write_entered_;
  934. return true;
  935. }
  936. return false;
  937. }
  938. void
  939. upgrade_mutex::unlock_and_lock_upgrade()
  940. {
  941. {
  942. boost::lock_guard<mutex_t> _(mut_);
  943. state_ = upgradable_entered_ | 1;
  944. }
  945. gate1_.notify_all();
  946. }
  947. } // thread_v2
  948. } // boost
  949. namespace boost {
  950. //using thread_v2::shared_mutex;
  951. using thread_v2::upgrade_mutex;
  952. typedef thread_v2::upgrade_mutex shared_mutex;
  953. }
  954. #endif