From f6ea549cf657efeb383681d3e5c6c709c168fe9a Mon Sep 17 00:00:00 2001 From: stakx Date: Sat, 23 Jun 2018 14:02:09 +0200 Subject: [PATCH] Reinstate upgradeable read locks Based on a review comment, this reinstates the upgradeable read locks that were originally taken before entering write locks. The intent of this PR is to deprecate `Lock`, not to make functional changes. While forgoing the upgradeable read locks in favor of enter- ing write locks right away might *possibly* be an optimization, this is a different concern and would need to be properly established using careful benchmarking. Let's do this another time. --- .../Internal/Utilities/SingletonDispenser.cs | 16 +++++++++---- .../Core/Internal/SynchronizedDictionary.cs | 23 ++++++++++++++++--- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/Castle.Core/Components.DictionaryAdapter/Xml/Internal/Utilities/SingletonDispenser.cs b/src/Castle.Core/Components.DictionaryAdapter/Xml/Internal/Utilities/SingletonDispenser.cs index 726b7adc8a..6aee638efc 100644 --- a/src/Castle.Core/Components.DictionaryAdapter/Xml/Internal/Utilities/SingletonDispenser.cs +++ b/src/Castle.Core/Components.DictionaryAdapter/Xml/Internal/Utilities/SingletonDispenser.cs @@ -65,7 +65,7 @@ private bool TryGetExistingItem(TKey key, out object item) locker.ExitReadLock(); } - locker.EnterWriteLock(); + locker.EnterUpgradeableReadLock(); try { if (items.TryGetValue(key, out item)) @@ -74,13 +74,21 @@ private bool TryGetExistingItem(TKey key, out object item) } else { - items[key] = item = new ManualResetEvent(false); - return false; + locker.EnterWriteLock(); + try + { + items[key] = item = new ManualResetEvent(false); + return false; + } + finally + { + locker.ExitWriteLock(); + } } } finally { - locker.ExitWriteLock(); + locker.ExitUpgradeableReadLock(); } } diff --git a/src/Castle.Core/Core/Internal/SynchronizedDictionary.cs b/src/Castle.Core/Core/Internal/SynchronizedDictionary.cs index 7b8d63a24d..59ab376cec 100644 --- a/src/Castle.Core/Core/Internal/SynchronizedDictionary.cs +++ b/src/Castle.Core/Core/Internal/SynchronizedDictionary.cs @@ -59,14 +59,31 @@ public TValue GetOrAdd(TKey key, Func valueFactory) itemsLock.ExitReadLock(); } - itemsLock.EnterWriteLock(); + itemsLock.EnterUpgradeableReadLock(); try { - return GetOrAddWithoutTakingLock(key, valueFactory); + if (items.TryGetValue(key, out value)) + { + return value; + } + else + { + itemsLock.EnterWriteLock(); + try + { + value = valueFactory.Invoke(key); + items.Add(key, value); + return value; + } + finally + { + itemsLock.ExitWriteLock(); + } + } } finally { - itemsLock.ExitWriteLock(); + itemsLock.ExitUpgradeableReadLock(); } }