Lean  $LEAN_TAG$
ReaderWriterLockSlimExtensions.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15 */
16 
17 using System;
18 using System.Threading;
19 
20 namespace QuantConnect.Util
21 {
22  /// <summary>
23  /// Provides extension methods to make working with the <see cref="ReaderWriterLockSlim"/> class easier
24  /// </summary>
25  public static class ReaderWriterLockSlimExtensions
26  {
27  /// <summary>
28  /// Opens the read lock
29  /// </summary>
30  /// <param name="readerWriterLockSlim">The lock to open for read</param>
31  /// <returns>A disposable reference which will release the lock upon disposal</returns>
32  public static IDisposable Read(this ReaderWriterLockSlim readerWriterLockSlim)
33  {
34  return new ReaderLockToken(readerWriterLockSlim);
35  }
36 
37  /// <summary>
38  /// Opens the write lock
39  /// </summary>
40  /// <param name="readerWriterLockSlim">The lock to open for write</param>
41  /// <returns>A disposale reference which will release thelock upon disposal</returns>
42  public static IDisposable Write(this ReaderWriterLockSlim readerWriterLockSlim)
43  {
44  return new WriteLockToken(readerWriterLockSlim);
45  }
46 
47  private sealed class ReaderLockToken : ReaderWriterLockSlimToken
48  {
49  public ReaderLockToken(ReaderWriterLockSlim readerWriterLockSlim)
50  : base(readerWriterLockSlim)
51  {
52  }
53 
54  protected override void EnterLock(ReaderWriterLockSlim readerWriterLockSlim)
55  {
56  readerWriterLockSlim.EnterReadLock();
57  }
58 
59  protected override void ExitLock(ReaderWriterLockSlim readerWriterLockSlim)
60  {
61  readerWriterLockSlim.ExitReadLock();
62  }
63  }
64 
65  private sealed class WriteLockToken : ReaderWriterLockSlimToken
66  {
67  public WriteLockToken(ReaderWriterLockSlim readerWriterLockSlim)
68  : base(readerWriterLockSlim)
69  {
70  }
71 
72  protected override void EnterLock(ReaderWriterLockSlim readerWriterLockSlim)
73  {
74  readerWriterLockSlim.EnterWriteLock();
75  }
76 
77  protected override void ExitLock(ReaderWriterLockSlim readerWriterLockSlim)
78  {
79  readerWriterLockSlim.ExitWriteLock();
80  }
81  }
82 
83  private abstract class ReaderWriterLockSlimToken : IDisposable
84  {
85  private ReaderWriterLockSlim _readerWriterLockSlim;
86 
87  public ReaderWriterLockSlimToken(ReaderWriterLockSlim readerWriterLockSlim)
88  {
89  _readerWriterLockSlim = readerWriterLockSlim;
90  // ReSharper disable once DoNotCallOverridableMethodsInConstructor -- we control the subclasses, this is fine
91  EnterLock(_readerWriterLockSlim);
92  }
93 
94  protected abstract void EnterLock(ReaderWriterLockSlim readerWriterLockSlim);
95  protected abstract void ExitLock(ReaderWriterLockSlim readerWriterLockSlim);
96 
97  public void Dispose()
98  {
99  if (_readerWriterLockSlim != null)
100  {
101  ExitLock(_readerWriterLockSlim);
102  _readerWriterLockSlim = null;
103  }
104  }
105  }
106  }
107 }