ReaderWriterLock.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #region Apache License
  2. //
  3. // Licensed to the Apache Software Foundation (ASF) under one or more
  4. // contributor license agreements. See the NOTICE file distributed with
  5. // this work for additional information regarding copyright ownership.
  6. // The ASF licenses this file to you under the Apache License, Version 2.0
  7. // (the "License"); you may not use this file except in compliance with
  8. // the License. You may obtain a copy of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS,
  14. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. // See the License for the specific language governing permissions and
  16. // limitations under the License.
  17. //
  18. #endregion
  19. #if (!NETCF)
  20. #define HAS_READERWRITERLOCK
  21. #endif
  22. #if NET_4_0 || MONO_4_0
  23. #define HAS_READERWRITERLOCKSLIM
  24. #endif
  25. using System;
  26. namespace log4net.Util
  27. {
  28. /// <summary>
  29. /// Defines a lock that supports single writers and multiple readers
  30. /// </summary>
  31. /// <remarks>
  32. /// <para>
  33. /// <c>ReaderWriterLock</c> is used to synchronize access to a resource.
  34. /// At any given time, it allows either concurrent read access for
  35. /// multiple threads, or write access for a single thread. In a
  36. /// situation where a resource is changed infrequently, a
  37. /// <c>ReaderWriterLock</c> provides better throughput than a simple
  38. /// one-at-a-time lock, such as <see cref="System.Threading.Monitor"/>.
  39. /// </para>
  40. /// <para>
  41. /// If a platform does not support a <c>System.Threading.ReaderWriterLock</c>
  42. /// implementation then all readers and writers are serialized. Therefore
  43. /// the caller must not rely on multiple simultaneous readers.
  44. /// </para>
  45. /// </remarks>
  46. /// <author>Nicko Cadell</author>
  47. public sealed class ReaderWriterLock
  48. {
  49. #region Instance Constructors
  50. /// <summary>
  51. /// Constructor
  52. /// </summary>
  53. /// <remarks>
  54. /// <para>
  55. /// Initializes a new instance of the <see cref="ReaderWriterLock" /> class.
  56. /// </para>
  57. /// </remarks>
  58. public ReaderWriterLock()
  59. {
  60. #if HAS_READERWRITERLOCK
  61. #if HAS_READERWRITERLOCKSLIM
  62. m_lock = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.SupportsRecursion);
  63. #else
  64. m_lock = new System.Threading.ReaderWriterLock();
  65. #endif
  66. #endif
  67. }
  68. #endregion Private Instance Constructors
  69. #region Public Methods
  70. /// <summary>
  71. /// Acquires a reader lock
  72. /// </summary>
  73. /// <remarks>
  74. /// <para>
  75. /// <see cref="AcquireReaderLock"/> blocks if a different thread has the writer
  76. /// lock, or if at least one thread is waiting for the writer lock.
  77. /// </para>
  78. /// </remarks>
  79. public void AcquireReaderLock()
  80. {
  81. #if HAS_READERWRITERLOCK
  82. #if HAS_READERWRITERLOCKSLIM
  83. // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443
  84. try { }
  85. finally
  86. {
  87. m_lock.EnterReadLock();
  88. }
  89. #else
  90. m_lock.AcquireReaderLock(-1);
  91. #endif
  92. #else
  93. System.Threading.Monitor.Enter(this);
  94. #endif
  95. }
  96. /// <summary>
  97. /// Decrements the lock count
  98. /// </summary>
  99. /// <remarks>
  100. /// <para>
  101. /// <see cref="ReleaseReaderLock"/> decrements the lock count. When the count
  102. /// reaches zero, the lock is released.
  103. /// </para>
  104. /// </remarks>
  105. public void ReleaseReaderLock()
  106. {
  107. #if HAS_READERWRITERLOCK
  108. #if HAS_READERWRITERLOCKSLIM
  109. m_lock.ExitReadLock();
  110. #else
  111. m_lock.ReleaseReaderLock();
  112. #endif
  113. #else
  114. System.Threading.Monitor.Exit(this);
  115. #endif
  116. }
  117. /// <summary>
  118. /// Acquires the writer lock
  119. /// </summary>
  120. /// <remarks>
  121. /// <para>
  122. /// This method blocks if another thread has a reader lock or writer lock.
  123. /// </para>
  124. /// </remarks>
  125. public void AcquireWriterLock()
  126. {
  127. #if HAS_READERWRITERLOCK
  128. #if HAS_READERWRITERLOCKSLIM
  129. // prevent ThreadAbort while updating state, see https://issues.apache.org/jira/browse/LOG4NET-443
  130. try { }
  131. finally
  132. {
  133. m_lock.EnterWriteLock();
  134. }
  135. #else
  136. m_lock.AcquireWriterLock(-1);
  137. #endif
  138. #else
  139. System.Threading.Monitor.Enter(this);
  140. #endif
  141. }
  142. /// <summary>
  143. /// Decrements the lock count on the writer lock
  144. /// </summary>
  145. /// <remarks>
  146. /// <para>
  147. /// ReleaseWriterLock decrements the writer lock count.
  148. /// When the count reaches zero, the writer lock is released.
  149. /// </para>
  150. /// </remarks>
  151. public void ReleaseWriterLock()
  152. {
  153. #if HAS_READERWRITERLOCK
  154. #if HAS_READERWRITERLOCKSLIM
  155. m_lock.ExitWriteLock();
  156. #else
  157. m_lock.ReleaseWriterLock();
  158. #endif
  159. #else
  160. System.Threading.Monitor.Exit(this);
  161. #endif
  162. }
  163. #endregion Public Methods
  164. #region Private Members
  165. #if HAS_READERWRITERLOCK
  166. #if HAS_READERWRITERLOCKSLIM
  167. private System.Threading.ReaderWriterLockSlim m_lock;
  168. #else
  169. private System.Threading.ReaderWriterLock m_lock;
  170. #endif
  171. #endif
  172. #endregion
  173. }
  174. }