Skip to content

Commit 7fc0424

Browse files
committed
NH-3811 Make table counter per thread (merge).
2 parents d1eb593 + 48d8f86 commit 7fc0424

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Reflection;
3+
using System.Security.Permissions;
4+
using System.Threading;
5+
6+
namespace NHibernate.Test
7+
{
8+
/// <summary>
9+
/// Helper class to execute a method on another thread, catching all exceptions then rethrowing them
10+
/// on another thread that calls Join().
11+
/// </summary>
12+
/// TODO: Explore if this can be merged with MultiThreadRunner (probably should add exception handling to the latter).
13+
class CrossThreadTestRunner
14+
{
15+
private Exception _lastException;
16+
private readonly Thread _thread;
17+
private readonly ThreadStart _start;
18+
19+
private const string remoteStackTraceFieldName = "_remoteStackTraceString";
20+
21+
private static readonly FieldInfo RemoteStackTraceField = typeof(Exception).GetField(remoteStackTraceFieldName,
22+
BindingFlags.Instance |
23+
BindingFlags.NonPublic);
24+
25+
public CrossThreadTestRunner(ThreadStart start)
26+
{
27+
_start = start;
28+
_thread = new Thread(Run);
29+
_thread.SetApartmentState(ApartmentState.STA);
30+
}
31+
32+
public void Start()
33+
{
34+
_lastException = null;
35+
_thread.Start();
36+
}
37+
38+
public void Join()
39+
{
40+
_thread.Join();
41+
42+
if (_lastException != null)
43+
{
44+
ThrowExceptionPreservingStack(_lastException);
45+
}
46+
}
47+
48+
private void Run()
49+
{
50+
try
51+
{
52+
_start.Invoke();
53+
}
54+
catch (Exception e)
55+
{
56+
_lastException = e;
57+
}
58+
}
59+
60+
[ReflectionPermission(SecurityAction.Demand)]
61+
private static void ThrowExceptionPreservingStack(Exception exception)
62+
{
63+
if (RemoteStackTraceField != null)
64+
{
65+
RemoteStackTraceField.SetValue(exception, exception.StackTrace + Environment.NewLine);
66+
}
67+
throw exception;
68+
}
69+
}
70+
}

src/NHibernate.Test/MappingTest/TableFixture.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System.Linq;
2+
using System.Threading;
13
using NHibernate.Dialect;
24
using NHibernate.Mapping;
35
using NUnit.Framework;
@@ -59,5 +61,45 @@ public void SchemaNameQuoted()
5961

6062
Assert.AreEqual("[schema].name", tbl.GetQualifiedName(dialect));
6163
}
64+
65+
[Test]
66+
public void TablesUniquelyNamed()
67+
{
68+
Table tbl1 = new Table();
69+
Table tbl2 = new Table();
70+
71+
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
72+
}
73+
74+
[Test]
75+
public void TablesUniquelyNamedOnlyWithinThread()
76+
{
77+
var uniqueIntegerList = new System.Collections.Concurrent.ConcurrentBag<int>();
78+
var method = new ThreadStart(() =>
79+
{
80+
Table tbl1 = new Table();
81+
Table tbl2 = new Table();
82+
83+
// Store these values for later comparison
84+
uniqueIntegerList.Add(tbl1.UniqueInteger);
85+
uniqueIntegerList.Add(tbl2.UniqueInteger);
86+
87+
// Ensure that within a thread we have unique integers
88+
Assert.AreEqual(tbl1.UniqueInteger + 1, tbl2.UniqueInteger);
89+
});
90+
91+
var thread1 = new CrossThreadTestRunner(method);
92+
var thread2 = new CrossThreadTestRunner(method);
93+
94+
thread1.Start();
95+
thread2.Start();
96+
97+
thread1.Join();
98+
thread2.Join();
99+
100+
// There should in total be 4 tables, but only two distinct identifiers.
101+
Assert.AreEqual(4, uniqueIntegerList.Count);
102+
Assert.AreEqual(2, uniqueIntegerList.Distinct().Count());
103+
}
62104
}
63105
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@
231231
<Compile Include="Criteria\MaterialResource.cs" />
232232
<Compile Include="Criteria\ProjectionsTest.cs" />
233233
<Compile Include="Criteria\Reptile.cs" />
234+
<Compile Include="CrossThreadTestRunner.cs" />
234235
<Compile Include="DialectTest\FunctionTests\SubstringSupportFixture.cs" />
235236
<Compile Include="DialectTest\FunctionTests\SequenceSupportFixture.cs" />
236237
<Compile Include="DialectTest\Ingres9DialectFixture.cs" />

src/NHibernate/Mapping/Table.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ public enum SchemaAction
2525
[Serializable]
2626
public class Table : IRelationalModel
2727
{
28+
[ThreadStatic]
2829
private static int tableCounter;
30+
2931
private readonly List<string> checkConstraints = new List<string>();
3032
private readonly LinkedHashMap<string, Column> columns = new LinkedHashMap<string, Column>();
3133
private readonly Dictionary<ForeignKeyKey, ForeignKey> foreignKeys = new Dictionary<ForeignKeyKey, ForeignKey>();

0 commit comments

Comments
 (0)