Skip to content

Commit 9b60f9e

Browse files
committed
NH-3885 - Addressed feedback
Only use ConcurrentDictionary through the public methods, not the interface methods.
1 parent 898184b commit 9b60f9e

File tree

5 files changed

+55
-62
lines changed

5 files changed

+55
-62
lines changed

src/NHibernate.Test/UtilityTest/ThreadSafeDictionaryFixture.cs

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Collections.Generic;
44
using System.Threading;
55
using log4net;
6-
using NHibernate.Util;
76
using NUnit.Framework;
87

98
namespace NHibernate.Test.UtilityTest
@@ -24,42 +23,36 @@ public ThreadSafeDictionaryFixture()
2423
[Test, Explicit]
2524
public void MultiThreadAccess()
2625
{
27-
MultiThreadRunner<IDictionary<int, int>>.ExecuteAction[] actions =
28-
new MultiThreadRunner<IDictionary<int, int>>.ExecuteAction[]
26+
MultiThreadRunner<ConcurrentDictionary<int, int>>.ExecuteAction[] actions =
27+
new MultiThreadRunner<ConcurrentDictionary<int, int>>.ExecuteAction[]
2928
{
30-
delegate(IDictionary<int, int> d)
29+
delegate(ConcurrentDictionary<int, int> d)
3130
{
32-
try
33-
{
34-
log.DebugFormat("T{0} Add", Thread.CurrentThread.Name);
35-
write++;
36-
d.Add(rnd.Next(), rnd.Next());
37-
}
38-
catch (ArgumentException)
39-
{
40-
// duplicated key
41-
}
31+
log.DebugFormat("T{0} Add", Thread.CurrentThread.Name);
32+
write++;
33+
d.TryAdd(rnd.Next(), rnd.Next());
4234
},
43-
delegate(IDictionary<int, int> d)
35+
delegate(ConcurrentDictionary<int, int> d)
4436
{
4537
log.DebugFormat("T{0} ContainsKey", Thread.CurrentThread.Name);
4638
read++;
4739
d.ContainsKey(rnd.Next());
4840
},
49-
delegate(IDictionary<int, int> d)
41+
delegate(ConcurrentDictionary<int, int> d)
5042
{
5143
log.DebugFormat("T{0} Remove", Thread.CurrentThread.Name);
5244
write++;
53-
d.Remove(rnd.Next());
45+
int value;
46+
d.TryRemove(rnd.Next(), out value);
5447
},
55-
delegate(IDictionary<int, int> d)
48+
delegate(ConcurrentDictionary<int, int> d)
5649
{
5750
log.DebugFormat("T{0} TryGetValue", Thread.CurrentThread.Name);
5851
read++;
5952
int val;
6053
d.TryGetValue(rnd.Next(), out val);
6154
},
62-
delegate(IDictionary<int, int> d)
55+
delegate(ConcurrentDictionary<int, int> d)
6356
{
6457
try
6558
{
@@ -72,25 +65,25 @@ public void MultiThreadAccess()
7265
// not foud key
7366
}
7467
},
75-
delegate(IDictionary<int, int> d)
68+
delegate(ConcurrentDictionary<int, int> d)
7669
{
7770
log.DebugFormat("T{0} set_this[]", Thread.CurrentThread.Name);
7871
write++;
7972
d[rnd.Next()] = rnd.Next();
8073
},
81-
delegate(IDictionary<int, int> d)
74+
delegate(ConcurrentDictionary<int, int> d)
8275
{
8376
log.DebugFormat("T{0} Keys", Thread.CurrentThread.Name);
8477
read++;
8578
IEnumerable<int> e = d.Keys;
8679
},
87-
delegate(IDictionary<int, int> d)
80+
delegate(ConcurrentDictionary<int, int> d)
8881
{
8982
log.DebugFormat("T{0} Values", Thread.CurrentThread.Name);
9083
read++;
9184
IEnumerable<int> e = d.Values;
9285
},
93-
delegate(IDictionary<int, int> d)
86+
delegate(ConcurrentDictionary<int, int> d)
9487
{
9588
log.DebugFormat("T{0} GetEnumerator", Thread.CurrentThread.Name);
9689
read++;
@@ -100,8 +93,8 @@ public void MultiThreadAccess()
10093
}
10194
},
10295
};
103-
MultiThreadRunner<IDictionary<int, int>> mtr = new MultiThreadRunner<IDictionary<int, int>>(20, actions);
104-
IDictionary<int, int> wrapper = new ConcurrentDictionary<int, int>();
96+
MultiThreadRunner<ConcurrentDictionary<int, int>> mtr = new MultiThreadRunner<ConcurrentDictionary<int, int>>(20, actions);
97+
ConcurrentDictionary<int, int> wrapper = new ConcurrentDictionary<int, int>();
10598
mtr.EndTimeout = 2000;
10699
mtr.Run(wrapper);
107100
log.DebugFormat("{0} reads, {1} writes -- elements {2}", read, write, wrapper.Count);

src/NHibernate/Impl/SessionFactoryImpl.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,10 @@ public SessionFactoryImpl(Configuration cfg, IMapping mapping, Settings settings
248248
if (cache != null)
249249
{
250250
caches.Add(cacheRegion, cache);
251-
((IDictionary<string, ICache>)allCacheRegions).Add(cache.RegionName, cache.Cache);
251+
if (!allCacheRegions.TryAdd(cache.RegionName, cache.Cache))
252+
{
253+
throw new HibernateException("Key already existed");
254+
}
252255
}
253256
}
254257
IEntityPersister cp = PersisterFactory.CreateClassPersister(model, cache, this, mapping);
@@ -968,7 +971,8 @@ public UpdateTimestampsCache UpdateTimestampsCache
968971

969972
public IDictionary<string, ICache> GetAllSecondLevelCacheRegions()
970973
{
971-
return allCacheRegions.ToDictionary(kv => kv.Key, kv => kv.Value);
974+
// ToArray creates a moment in time snapshot
975+
return allCacheRegions.ToArray().ToDictionary(kv => kv.Key, kv => kv.Value);
972976
}
973977

974978
public ICache GetSecondLevelCacheRegion(string regionName)

src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@
77
#endregion
88

99
using System.Collections.Concurrent;
10-
using System.Collections.Generic;
11-
using NHibernate.Util;
1210

1311
namespace NHibernate.Proxy.DynamicProxy
1412
{
1513
public class ProxyCache : IProxyCache
1614
{
17-
private static readonly IDictionary<ProxyCacheEntry, System.Type> cache = new ConcurrentDictionary<ProxyCacheEntry, System.Type>();
15+
private static readonly ConcurrentDictionary<ProxyCacheEntry, System.Type> cache = new ConcurrentDictionary<ProxyCacheEntry, System.Type>();
1816

1917
#region IProxyCache Members
2018

src/NHibernate/SqlTypes/SqlTypeFactory.cs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Data;
4-
using System.Collections.Generic;
54
using System.Runtime.CompilerServices;
6-
using NHibernate.Util;
75

86
namespace NHibernate.SqlTypes
97
{
@@ -15,7 +13,7 @@ public static class SqlTypeFactory
1513
{
1614
// key = typeof(sqlType).Name : ie - BinarySqlType(l), BooleanSqlType, DecimalSqlType(p,s)
1715
// value = SqlType
18-
private static readonly IDictionary<string, SqlType> SqlTypes =
16+
private static readonly ConcurrentDictionary<string, SqlType> SqlTypes =
1917
new ConcurrentDictionary<string, SqlType>(4 * System.Environment.ProcessorCount, 128);
2018

2119
public static readonly SqlType Guid = new SqlType(DbType.Guid);
@@ -45,30 +43,14 @@ public static class SqlTypeFactory
4543
private static T GetTypeWithLen<T>(int length, TypeWithLenCreateDelegate createDelegate) where T : SqlType
4644
{
4745
string key = GetKeyForLengthBased(typeof (T).Name, length);
48-
SqlType result;
49-
if (!SqlTypes.TryGetValue(key, out result))
50-
{
51-
lock(SqlTypes)
52-
{
53-
if (!SqlTypes.TryGetValue(key, out result))
54-
{
55-
result = createDelegate(length);
56-
SqlTypes.Add(key, result);
57-
}
58-
}
59-
}
46+
SqlType result = SqlTypes.GetOrAdd(key, k => createDelegate(length));
6047
return (T) result;
6148
}
6249

6350
private static SqlType GetTypeWithPrecision(DbType dbType, byte precision, byte scale)
6451
{
6552
string key = GetKeyForPrecisionScaleBased(dbType.ToString(), precision, scale);
66-
SqlType result;
67-
if (!SqlTypes.TryGetValue(key, out result))
68-
{
69-
result = new SqlType(dbType, precision, scale);
70-
SqlTypes.Add(key, result);
71-
}
53+
SqlType result = SqlTypes.GetOrAdd(key, k => new SqlType(dbType, precision, scale));
7254
return result;
7355
}
7456

src/NHibernate/Type/TypeFactory.cs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections;
32
using System.Collections.Concurrent;
43
using System.Collections.Generic;
54
using System.Globalization;
@@ -8,7 +7,6 @@
87
using System.Xml.Linq;
98
using NHibernate.Bytecode;
109
using NHibernate.Classic;
11-
using NHibernate.Engine;
1210
using NHibernate.SqlTypes;
1311
using NHibernate.UserTypes;
1412
using NHibernate.Util;
@@ -61,13 +59,13 @@ private enum TypeClassification
6159
* "System.String(l)" -> instance of StringType with specified l
6260
*/
6361

64-
private static readonly IDictionary<string, IType> typeByTypeOfName =
62+
private static readonly ConcurrentDictionary<string, IType> typeByTypeOfName =
6563
new ConcurrentDictionary<string, IType>();
6664

67-
private static readonly IDictionary<string, GetNullableTypeWithLength> getTypeDelegatesWithLength =
65+
private static readonly ConcurrentDictionary<string, GetNullableTypeWithLength> getTypeDelegatesWithLength =
6866
new ConcurrentDictionary<string, GetNullableTypeWithLength>();
6967

70-
private static readonly IDictionary<string, GetNullableTypeWithPrecision> getTypeDelegatesWithPrecision =
68+
private static readonly ConcurrentDictionary<string, GetNullableTypeWithPrecision> getTypeDelegatesWithPrecision =
7169
new ConcurrentDictionary<string, GetNullableTypeWithPrecision>();
7270

7371
private delegate NullableType GetNullableTypeWithLength(int length); // Func<int, NullableType>
@@ -134,7 +132,10 @@ private static void RegisterType(IType nhibernateType, IEnumerable<string> alias
134132
foreach (var alias in typeAliases)
135133
{
136134
typeByTypeOfName[alias] = nhibernateType;
137-
getTypeDelegatesWithLength.Add(alias, ctorLength);
135+
if (!getTypeDelegatesWithLength.TryAdd(alias, ctorLength))
136+
{
137+
throw new HibernateException("Key already existed");
138+
}
138139
}
139140
}
140141

@@ -144,7 +145,10 @@ private static void RegisterType(IType nhibernateType, IEnumerable<string> alias
144145
foreach (var alias in typeAliases)
145146
{
146147
typeByTypeOfName[alias] = nhibernateType;
147-
getTypeDelegatesWithPrecision.Add(alias, ctorPrecision);
148+
if (!getTypeDelegatesWithPrecision.TryAdd(alias, ctorPrecision))
149+
{
150+
throw new HibernateException("Key already existed");
151+
}
148152
}
149153
}
150154

@@ -403,18 +407,30 @@ internal static IType BuiltInType(string typeName, byte precision, byte scale)
403407

404408
private static void AddToTypeOfName(string key, IType type)
405409
{
406-
typeByTypeOfName.Add(key, type);
407-
typeByTypeOfName.Add(type.Name, type);
410+
if (!typeByTypeOfName.TryAdd(key, type))
411+
{
412+
throw new HibernateException("Key already existed");
413+
}
414+
if (!typeByTypeOfName.TryAdd(type.Name, type))
415+
{
416+
throw new HibernateException("Key already existed");
417+
}
408418
}
409419

410420
private static void AddToTypeOfNameWithLength(string key, IType type)
411421
{
412-
typeByTypeOfName.Add(key, type);
422+
if (!typeByTypeOfName.TryAdd(key, type))
423+
{
424+
throw new HibernateException("Key already existed");
425+
}
413426
}
414427

415428
private static void AddToTypeOfNameWithPrecision(string key, IType type)
416429
{
417-
typeByTypeOfName.Add(key, type);
430+
if (!typeByTypeOfName.TryAdd(key, type))
431+
{
432+
throw new HibernateException("Key already existed");
433+
}
418434
}
419435

420436
private static string GetKeyForLengthBased(string name, int length)

0 commit comments

Comments
 (0)