Last active
August 29, 2015 14:19
-
-
Save nillis/0c63930229ac9164ff09 to your computer and use it in GitHub Desktop.
SingleInstance lock replaced by ReaderWriterLockSlim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// Protects shared instances from concurrent access. Other members and the base class are threadsafe. | |
/// </summary> | |
readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); | |
~LifetimeScope() | |
{ | |
if (_cacheLock != null) _cacheLock.Dispose(); | |
} | |
/// <summary> | |
/// Try to retrieve an instance based on a GUID key. If the instance | |
/// does not exist, invoke <paramref name="creator"/> to create it. | |
/// </summary> | |
/// <param name="id">Key to look up.</param> | |
/// <param name="creator">Creation function.</param> | |
/// <returns>An instance.</returns> | |
public object GetOrCreateAndShare(Guid id, Func<object> creator) | |
{ | |
if (creator == null) | |
{ | |
throw new ArgumentNullException("creator"); | |
} | |
object result; | |
// 1. try to get the shared instance using a read lock which can be acquired by multiple threads | |
_cacheLock.EnterReadLock(); | |
try | |
{ | |
if (_sharedInstances.TryGetValue(id, out result)) | |
{ | |
return result; | |
} | |
} | |
finally | |
{ | |
_cacheLock.ExitReadLock(); | |
} | |
// 2. when the instance couldn't be fetched, enter the upgradeablereadlock which can be acquired by only one thread | |
_cacheLock.EnterUpgradeableReadLock(); | |
try | |
{ | |
if (!_sharedInstances.TryGetValue(id, out result)) | |
{ | |
// 3. when the instance still couldn't be fetched, enter the write lock which also can be acquired by only one thread | |
_cacheLock.EnterWriteLock(); | |
try | |
{ | |
result = creator(); | |
_sharedInstances.Add(id, result); | |
} | |
finally | |
{ | |
_cacheLock.ExitWriteLock(); | |
} | |
} | |
return result; | |
} | |
finally | |
{ | |
_cacheLock.ExitUpgradeableReadLock(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment