ReaderWriterLockSlimTest.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. //
  2. // ReaderWriterLockSlimTest.cs
  3. //
  4. // Authors:
  5. // Marek Safar ([email protected])
  6. //
  7. // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. using System;
  29. using NUnit.Framework;
  30. using System.Threading;
  31. using System.Threading.Tasks;
  32. using System.Linq;
  33. namespace MonoTests.System.Threading
  34. {
  35. [TestFixture]
  36. public class ReaderWriterLockSlimTests
  37. {
  38. [Test]
  39. public void DefaultValues ()
  40. {
  41. var v = new ReaderWriterLockSlim ();
  42. Assert.AreEqual (0, v.CurrentReadCount, "1");
  43. Assert.AreEqual (false, v.IsReadLockHeld, "2");
  44. Assert.AreEqual (false, v.IsUpgradeableReadLockHeld, "3");
  45. Assert.AreEqual (false, v.IsWriteLockHeld, "4");
  46. Assert.AreEqual (LockRecursionPolicy.NoRecursion, v.RecursionPolicy, "5");
  47. Assert.AreEqual (0, v.RecursiveReadCount, "6");
  48. Assert.AreEqual (0, v.RecursiveUpgradeCount, "7");
  49. Assert.AreEqual (0, v.RecursiveWriteCount, "8");
  50. Assert.AreEqual (0, v.WaitingReadCount, "9");
  51. Assert.AreEqual (0, v.WaitingUpgradeCount, "10");
  52. Assert.AreEqual (0, v.WaitingWriteCount, "11");
  53. }
  54. [Test]
  55. public void Dispose_Errors ()
  56. {
  57. var v = new ReaderWriterLockSlim ();
  58. v.Dispose ();
  59. try {
  60. v.EnterUpgradeableReadLock ();
  61. Assert.Fail ("1");
  62. } catch (ObjectDisposedException) {
  63. }
  64. try {
  65. v.EnterReadLock ();
  66. Assert.Fail ("2");
  67. } catch (ObjectDisposedException) {
  68. }
  69. try {
  70. v.EnterWriteLock ();
  71. Assert.Fail ("3");
  72. } catch (ObjectDisposedException) {
  73. }
  74. }
  75. [Test]
  76. public void TryEnterReadLock_OutOfRange ()
  77. {
  78. var v = new ReaderWriterLockSlim ();
  79. try {
  80. v.TryEnterReadLock (-2);
  81. Assert.Fail ("1");
  82. } catch (ArgumentOutOfRangeException) {
  83. }
  84. try {
  85. v.TryEnterReadLock (TimeSpan.MaxValue);
  86. Assert.Fail ("2");
  87. } catch (ArgumentOutOfRangeException) {
  88. }
  89. try {
  90. v.TryEnterReadLock (TimeSpan.MinValue);
  91. Assert.Fail ("3");
  92. } catch (ArgumentOutOfRangeException) {
  93. }
  94. }
  95. [Test]
  96. public void TryEnterUpgradeableReadLock_OutOfRange ()
  97. {
  98. var v = new ReaderWriterLockSlim ();
  99. try {
  100. v.TryEnterUpgradeableReadLock (-2);
  101. Assert.Fail ("1");
  102. } catch (ArgumentOutOfRangeException) {
  103. }
  104. try {
  105. v.TryEnterUpgradeableReadLock (TimeSpan.MaxValue);
  106. Assert.Fail ("2");
  107. } catch (ArgumentOutOfRangeException) {
  108. }
  109. try {
  110. v.TryEnterUpgradeableReadLock (TimeSpan.MinValue);
  111. Assert.Fail ("3");
  112. } catch (ArgumentOutOfRangeException) {
  113. }
  114. }
  115. [Test]
  116. public void TryEnterWriteLock_OutOfRange ()
  117. {
  118. var v = new ReaderWriterLockSlim ();
  119. try {
  120. v.TryEnterWriteLock (-2);
  121. Assert.Fail ("1");
  122. } catch (ArgumentOutOfRangeException) {
  123. }
  124. try {
  125. v.TryEnterWriteLock (TimeSpan.MaxValue);
  126. Assert.Fail ("2");
  127. } catch (ArgumentOutOfRangeException) {
  128. }
  129. try {
  130. v.TryEnterWriteLock (TimeSpan.MinValue);
  131. Assert.Fail ("3");
  132. } catch (ArgumentOutOfRangeException) {
  133. }
  134. }
  135. [Test, ExpectedException (typeof (SynchronizationLockException))]
  136. public void ExitReadLock ()
  137. {
  138. var v = new ReaderWriterLockSlim ();
  139. v.ExitReadLock ();
  140. }
  141. [Test, ExpectedException (typeof (SynchronizationLockException))]
  142. public void ExitWriteLock ()
  143. {
  144. var v = new ReaderWriterLockSlim ();
  145. v.ExitWriteLock ();
  146. }
  147. [Test]
  148. public void EnterReadLock_NoRecursionError ()
  149. {
  150. var v = new ReaderWriterLockSlim ();
  151. v.EnterReadLock ();
  152. Assert.AreEqual (1, v.RecursiveReadCount);
  153. try {
  154. v.EnterReadLock ();
  155. Assert.Fail ("1");
  156. } catch (LockRecursionException) {
  157. }
  158. try {
  159. v.EnterWriteLock ();
  160. Assert.Fail ("2");
  161. } catch (LockRecursionException) {
  162. }
  163. }
  164. [Test]
  165. public void EnterReadLock ()
  166. {
  167. var v = new ReaderWriterLockSlim ();
  168. v.EnterReadLock ();
  169. Assert.IsTrue (v.IsReadLockHeld, "A");
  170. Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
  171. Assert.AreEqual (1, v.RecursiveReadCount, "A2");
  172. Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
  173. Assert.AreEqual (0, v.WaitingReadCount, "A4");
  174. Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
  175. Assert.AreEqual (0, v.WaitingWriteCount, "A6");
  176. v.ExitReadLock ();
  177. v.EnterReadLock ();
  178. Assert.IsTrue (v.IsReadLockHeld, "B");
  179. Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
  180. Assert.AreEqual (1, v.RecursiveReadCount, "B2");
  181. Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
  182. Assert.AreEqual (0, v.WaitingReadCount, "B4");
  183. Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
  184. Assert.AreEqual (0, v.WaitingWriteCount, "B6");
  185. v.ExitReadLock ();
  186. }
  187. [Test]
  188. public void EnterWriteLock_NoRecursionError ()
  189. {
  190. var v = new ReaderWriterLockSlim ();
  191. v.EnterWriteLock ();
  192. Assert.AreEqual (1, v.RecursiveWriteCount);
  193. try {
  194. v.EnterWriteLock ();
  195. Assert.Fail ("1");
  196. } catch (LockRecursionException) {
  197. }
  198. try {
  199. v.EnterReadLock ();
  200. Assert.Fail ("2");
  201. } catch (LockRecursionException) {
  202. }
  203. }
  204. [Test]
  205. public void EnterWriteLock ()
  206. {
  207. var v = new ReaderWriterLockSlim ();
  208. v.EnterWriteLock ();
  209. Assert.IsTrue (v.IsWriteLockHeld, "A");
  210. Assert.AreEqual (1, v.RecursiveWriteCount, "A1");
  211. Assert.AreEqual (0, v.RecursiveReadCount, "A2");
  212. Assert.AreEqual (0, v.RecursiveUpgradeCount, "A3");
  213. Assert.AreEqual (0, v.WaitingReadCount, "A4");
  214. Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
  215. Assert.AreEqual (0, v.WaitingWriteCount, "A6");
  216. v.ExitWriteLock ();
  217. v.EnterWriteLock ();
  218. Assert.IsTrue (v.IsWriteLockHeld, "B");
  219. Assert.AreEqual (1, v.RecursiveWriteCount, "B1");
  220. Assert.AreEqual (0, v.RecursiveReadCount, "B2");
  221. Assert.AreEqual (0, v.RecursiveUpgradeCount, "B3");
  222. Assert.AreEqual (0, v.WaitingReadCount, "B4");
  223. Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
  224. Assert.AreEqual (0, v.WaitingWriteCount, "B6");
  225. v.ExitWriteLock ();
  226. }
  227. [Test]
  228. public void EnterUpgradeableReadLock_NoRecursionError ()
  229. {
  230. var v = new ReaderWriterLockSlim ();
  231. v.EnterUpgradeableReadLock ();
  232. Assert.AreEqual (1, v.RecursiveUpgradeCount);
  233. try {
  234. v.EnterUpgradeableReadLock ();
  235. Assert.Fail ("2");
  236. } catch (LockRecursionException) {
  237. }
  238. }
  239. [Test]
  240. public void EnterUpgradeableReadLock ()
  241. {
  242. var v = new ReaderWriterLockSlim ();
  243. v.EnterUpgradeableReadLock ();
  244. Assert.IsTrue (v.IsUpgradeableReadLockHeld, "A");
  245. Assert.AreEqual (0, v.RecursiveWriteCount, "A1");
  246. Assert.AreEqual (0, v.RecursiveReadCount, "A2");
  247. Assert.AreEqual (1, v.RecursiveUpgradeCount, "A3");
  248. Assert.AreEqual (0, v.WaitingReadCount, "A4");
  249. Assert.AreEqual (0, v.WaitingUpgradeCount, "A5");
  250. Assert.AreEqual (0, v.WaitingWriteCount, "A6");
  251. v.ExitUpgradeableReadLock ();
  252. v.EnterUpgradeableReadLock ();
  253. Assert.IsTrue (v.IsUpgradeableReadLockHeld, "B");
  254. Assert.AreEqual (0, v.RecursiveWriteCount, "B1");
  255. Assert.AreEqual (0, v.RecursiveReadCount, "B2");
  256. Assert.AreEqual (1, v.RecursiveUpgradeCount, "B3");
  257. Assert.AreEqual (0, v.WaitingReadCount, "B4");
  258. Assert.AreEqual (0, v.WaitingUpgradeCount, "B5");
  259. Assert.AreEqual (0, v.WaitingWriteCount, "B6");
  260. v.EnterReadLock ();
  261. v.ExitUpgradeableReadLock ();
  262. Assert.IsTrue (v.IsReadLockHeld, "C");
  263. Assert.AreEqual (0, v.RecursiveWriteCount, "C1");
  264. Assert.AreEqual (1, v.RecursiveReadCount, "C2");
  265. Assert.AreEqual (0, v.RecursiveUpgradeCount, "C3");
  266. Assert.AreEqual (0, v.WaitingReadCount, "C4");
  267. Assert.AreEqual (0, v.WaitingUpgradeCount, "C5");
  268. Assert.AreEqual (0, v.WaitingWriteCount, "C6");
  269. v.ExitReadLock ();
  270. }
  271. [Test]
  272. public void EnterReadLock_MultiRead ()
  273. {
  274. var v = new ReaderWriterLockSlim ();
  275. int local = 10;
  276. var r = from i in Enumerable.Range (1, 30) select new Thread (() => {
  277. // Just to cause some contention
  278. Thread.Sleep (100);
  279. v.EnterReadLock ();
  280. Assert.AreEqual (10, local);
  281. });
  282. var threads = r.ToList ();
  283. foreach (var t in threads) {
  284. t.Start ();
  285. }
  286. foreach (var t in threads) {
  287. // Console.WriteLine (t.ThreadState);
  288. t.Join ();
  289. }
  290. }
  291. [Test]
  292. public void TryEnterWriteLock_WhileReading ()
  293. {
  294. var v = new ReaderWriterLockSlim ();
  295. AutoResetEvent ev = new AutoResetEvent (false);
  296. AutoResetEvent ev2 = new AutoResetEvent (false);
  297. Thread t1 = new Thread (() => {
  298. v.EnterReadLock ();
  299. ev2.Set ();
  300. ev.WaitOne ();
  301. v.ExitReadLock ();
  302. });
  303. t1.Start ();
  304. ev2.WaitOne ();
  305. Assert.IsFalse (v.TryEnterWriteLock (100));
  306. ev.Set ();
  307. t1.Join ();
  308. Assert.IsTrue (v.TryEnterWriteLock (100));
  309. }
  310. [Test]
  311. public void EnterWriteLock_MultiRead ()
  312. {
  313. var v = new ReaderWriterLockSlim ();
  314. int local = 10;
  315. var r = from i in Enumerable.Range (1, 10) select new Thread (() => {
  316. v.EnterReadLock ();
  317. Assert.AreEqual (11, local);
  318. });
  319. v.EnterWriteLock ();
  320. var threads = r.ToList ();
  321. foreach (var t in threads) {
  322. t.Start ();
  323. }
  324. Thread.Sleep (200);
  325. local = 11;
  326. // FIXME: Don't rely on Thread.Sleep (200)
  327. Assert.AreEqual (0, v.WaitingWriteCount, "in waiting write");
  328. Assert.AreEqual (10, v.WaitingReadCount, "in waiting read");
  329. Assert.AreEqual (0, v.WaitingUpgradeCount, "in waiting upgrade");
  330. v.ExitWriteLock ();
  331. foreach (var t in threads) {
  332. // Console.WriteLine (t.ThreadState);
  333. t.Join ();
  334. }
  335. }
  336. [Test]
  337. public void EnterWriteLock_After_ExitUpgradeableReadLock ()
  338. {
  339. var v = new ReaderWriterLockSlim ();
  340. v.EnterUpgradeableReadLock ();
  341. Assert.IsTrue (v.TryEnterWriteLock (100));
  342. v.ExitWriteLock ();
  343. v.ExitUpgradeableReadLock ();
  344. Assert.IsTrue (v.TryEnterWriteLock (100));
  345. v.ExitWriteLock ();
  346. }
  347. #if NET_4_0
  348. [Test]
  349. public void EnterWriteLockWhileInUpgradeAndOtherWaiting ()
  350. {
  351. var v = new ReaderWriterLockSlim ();
  352. var task2 = new Task(() => {
  353. v.EnterWriteLock();
  354. v.ExitWriteLock();
  355. });
  356. var task1 = new Task(() =>
  357. {
  358. v.EnterUpgradeableReadLock ();
  359. task2.Start ();
  360. Thread.Sleep (100);
  361. v.EnterWriteLock ();
  362. v.ExitWriteLock ();
  363. v.ExitUpgradeableReadLock ();
  364. });
  365. task1.Start ();
  366. Assert.IsTrue (task1.Wait (500));
  367. }
  368. #endif
  369. [Test]
  370. public void RecursiveReadLockTest ()
  371. {
  372. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  373. Assert.IsTrue (v.TryEnterReadLock (100), "#1");
  374. Assert.IsTrue (v.TryEnterReadLock (100), "#2");
  375. Assert.IsTrue (v.TryEnterReadLock (100), "#3");
  376. Assert.AreEqual (3, v.RecursiveReadCount);
  377. }
  378. [Test]
  379. public void RecursiveReadPlusWriteLockTest ()
  380. {
  381. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  382. try {
  383. v.EnterReadLock ();
  384. v.EnterWriteLock ();
  385. Assert.Fail ("1");
  386. } catch (LockRecursionException ex) {
  387. Assert.IsNotNull (ex, "#1");
  388. }
  389. }
  390. [Test]
  391. public void RecursiveReadPlusUpgradeableLockTest ()
  392. {
  393. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  394. try {
  395. v.EnterReadLock ();
  396. v.EnterUpgradeableReadLock ();
  397. Assert.Fail ("1");
  398. } catch (LockRecursionException ex) {
  399. Assert.IsNotNull (ex, "#1");
  400. }
  401. }
  402. [Test]
  403. public void RecursiveWriteLockTest ()
  404. {
  405. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  406. Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
  407. Assert.IsTrue (v.TryEnterWriteLock (100), "#2");
  408. Assert.IsTrue (v.TryEnterWriteLock (100), "#3");
  409. Assert.AreEqual (3, v.RecursiveWriteCount);
  410. }
  411. [Test]
  412. public void RecursiveWritePlusReadLockTest ()
  413. {
  414. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  415. Assert.IsTrue (v.TryEnterWriteLock (100), "#1");
  416. Assert.AreEqual (1, v.RecursiveWriteCount, "1b");
  417. Assert.AreEqual (0, v.RecursiveReadCount, "1c");
  418. Assert.IsTrue (v.TryEnterReadLock (100), "#2");
  419. Assert.AreEqual (1, v.RecursiveWriteCount, "2b");
  420. Assert.AreEqual (1, v.RecursiveReadCount, "2c");
  421. Assert.IsTrue (v.TryEnterReadLock (100), "#3");
  422. Assert.AreEqual (1, v.RecursiveWriteCount, "3b");
  423. Assert.AreEqual (2, v.RecursiveReadCount, "3c");
  424. v.ExitReadLock ();
  425. Assert.AreEqual (1, v.RecursiveWriteCount, "4b");
  426. Assert.AreEqual (1, v.RecursiveReadCount, "4c");
  427. }
  428. [Test]
  429. public void RecursiveUpgradeableReadLockTest ()
  430. {
  431. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  432. Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#1");
  433. Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#2");
  434. Assert.IsTrue (v.TryEnterUpgradeableReadLock (100), "#3");
  435. Assert.AreEqual (3, v.RecursiveUpgradeCount);
  436. }
  437. [Test]
  438. public void RecursiveReadPropertiesTest ()
  439. {
  440. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  441. v.EnterReadLock ();
  442. v.EnterReadLock ();
  443. Assert.AreEqual (true, v.IsReadLockHeld, "#1a");
  444. Assert.AreEqual (1, v.CurrentReadCount, "#2a");
  445. Assert.AreEqual (2, v.RecursiveReadCount, "#3a");
  446. bool rLock = true;
  447. int cReadCount = -1, rReadCount = -1;
  448. Thread t = new Thread ((_) => {
  449. rLock = v.IsReadLockHeld;
  450. cReadCount = v.CurrentReadCount;
  451. rReadCount = v.RecursiveReadCount;
  452. });
  453. t.Start ();
  454. t.Join ();
  455. Assert.AreEqual (false, rLock, "#1b");
  456. Assert.AreEqual (1, cReadCount, "#2b");
  457. Assert.AreEqual (0, rReadCount, "#3b");
  458. }
  459. [Test]
  460. public void RecursiveUpgradePropertiesTest ()
  461. {
  462. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  463. v.EnterUpgradeableReadLock ();
  464. v.EnterUpgradeableReadLock ();
  465. Assert.AreEqual (true, v.IsUpgradeableReadLockHeld, "#1a");
  466. Assert.AreEqual (false, v.IsReadLockHeld, "#11a");
  467. Assert.AreEqual (0, v.CurrentReadCount, "#2a");
  468. Assert.AreEqual (2, v.RecursiveUpgradeCount, "#3a");
  469. bool upLock = false, rLock = false;
  470. int rCount = -1, rUCount = -1;
  471. Thread t = new Thread ((_) => {
  472. upLock = v.IsUpgradeableReadLockHeld;
  473. rLock = v.IsReadLockHeld;
  474. rCount = v.CurrentReadCount;
  475. rUCount = v.RecursiveUpgradeCount;
  476. });
  477. t.Start ();
  478. t.Join ();
  479. Assert.AreEqual (false, upLock, "#1b");
  480. Assert.AreEqual (false, rLock, "#11b");
  481. Assert.AreEqual (0, rCount, "#2b");
  482. Assert.AreEqual (0, rUCount, "#3b");
  483. }
  484. [Test]
  485. public void RecursiveWritePropertiesTest ()
  486. {
  487. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  488. v.EnterWriteLock ();
  489. v.EnterWriteLock ();
  490. Assert.AreEqual (true, v.IsWriteLockHeld, "#1a");
  491. Assert.AreEqual (2, v.RecursiveWriteCount, "#3a");
  492. bool wLock = false;
  493. int rWrite = -1;
  494. Thread t = new Thread ((_) => {
  495. wLock = v.IsWriteLockHeld;
  496. rWrite = v.RecursiveWriteCount;
  497. });
  498. t.Start ();
  499. t.Join ();
  500. Assert.AreEqual (false, wLock, "#1b");
  501. Assert.AreEqual (0, rWrite, "#3b");
  502. }
  503. [Test]
  504. public void RecursiveEnterExitReadTest ()
  505. {
  506. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  507. v.EnterReadLock ();
  508. v.EnterReadLock ();
  509. v.EnterReadLock ();
  510. Assert.IsTrue (v.IsReadLockHeld);
  511. Assert.AreEqual (3, v.RecursiveReadCount);
  512. v.ExitReadLock ();
  513. Assert.IsTrue (v.IsReadLockHeld);
  514. Assert.AreEqual (2, v.RecursiveReadCount);
  515. }
  516. [Test]
  517. public void RecursiveEnterExitWriteTest ()
  518. {
  519. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  520. v.EnterWriteLock ();
  521. v.EnterWriteLock ();
  522. v.EnterWriteLock ();
  523. Assert.IsTrue (v.IsWriteLockHeld);
  524. Assert.AreEqual (3, v.RecursiveWriteCount);
  525. v.ExitWriteLock ();
  526. v.ExitWriteLock ();
  527. Assert.IsTrue (v.IsWriteLockHeld);
  528. Assert.AreEqual (1, v.RecursiveWriteCount);
  529. }
  530. [Test]
  531. public void RecursiveEnterExitUpgradableTest ()
  532. {
  533. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  534. v.EnterUpgradeableReadLock ();
  535. v.EnterUpgradeableReadLock ();
  536. v.EnterUpgradeableReadLock ();
  537. Assert.IsTrue (v.IsUpgradeableReadLockHeld);
  538. Assert.AreEqual (3, v.RecursiveUpgradeCount);
  539. v.ExitUpgradeableReadLock ();
  540. Assert.IsTrue (v.IsUpgradeableReadLockHeld);
  541. Assert.AreEqual (2, v.RecursiveUpgradeCount);
  542. }
  543. [Test]
  544. public void RecursiveWriteUpgradeReadTest ()
  545. {
  546. var rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
  547. rwlock.EnterWriteLock ();
  548. Assert.IsTrue (rwlock.IsWriteLockHeld);
  549. rwlock.EnterUpgradeableReadLock ();
  550. Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
  551. rwlock.EnterReadLock ();
  552. Assert.IsTrue (rwlock.IsReadLockHeld);
  553. rwlock.ExitUpgradeableReadLock();
  554. Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
  555. Assert.IsTrue (rwlock.IsReadLockHeld);
  556. Assert.IsTrue (rwlock.IsWriteLockHeld);
  557. rwlock.ExitReadLock ();
  558. Assert.IsTrue (rwlock.IsWriteLockHeld);
  559. }
  560. [Test]
  561. public void RecursiveWriteUpgradeTest ()
  562. {
  563. ReaderWriterLockSlim rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
  564. rwlock.EnterWriteLock ();
  565. Assert.IsTrue (rwlock.IsWriteLockHeld);
  566. rwlock.EnterUpgradeableReadLock ();
  567. Assert.IsTrue (rwlock.IsUpgradeableReadLockHeld);
  568. rwlock.ExitUpgradeableReadLock ();
  569. Assert.IsFalse (rwlock.IsUpgradeableReadLockHeld);
  570. Assert.IsTrue (rwlock.IsWriteLockHeld);
  571. rwlock.ExitWriteLock ();
  572. Assert.IsFalse (rwlock.IsWriteLockHeld);
  573. rwlock.EnterWriteLock ();
  574. Assert.IsTrue (rwlock.IsWriteLockHeld);
  575. }
  576. [Test]
  577. public void RecursiveWriteReadAcquisitionInterleaving ()
  578. {
  579. var v = new ReaderWriterLockSlim (LockRecursionPolicy.SupportsRecursion);
  580. v.EnterWriteLock ();
  581. Assert.IsTrue (v.IsWriteLockHeld, "#1");
  582. bool result = true;
  583. var t = new Thread (delegate () {
  584. result = v.TryEnterReadLock (100);
  585. });
  586. t.Start ();
  587. t.Join ();
  588. Assert.IsFalse (result, "#2");
  589. v.ExitWriteLock ();
  590. t = new Thread (delegate () {
  591. result = v.TryEnterReadLock (100);
  592. });
  593. t.Start ();
  594. t.Join ();
  595. Assert.IsTrue (result, "#3");
  596. }
  597. }
  598. }