Browse Source

threading: resolve recursive parallelization, preventing deadlocks

Signed-off-by: Christoph Ruegg <git@cdrnet.ch>
pull/2/head
Christoph Ruegg 17 years ago
parent
commit
63d159c826
  1. 8
      src/Numerics/Threading/Parallel.cs
  2. 16
      src/Numerics/Threading/ThreadQueue.cs
  3. 43
      src/UnitTests/ThreadingTests/ParallelTest.cs

8
src/Numerics/Threading/Parallel.cs

@ -67,7 +67,9 @@ namespace MathNet.Numerics.Threading
// fast forward execution in case parallelization is disabled // fast forward execution in case parallelization is disabled
// (cdrnet, 200908): should we fast forward on STA threads as well? // (cdrnet, 200908): should we fast forward on STA threads as well?
if (Control.DisableParallelization || ThreadQueue.ThreadCount <= 1) if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{ {
for (int i = fromInclusive; i < toExclusive; i++) for (int i = fromInclusive; i < toExclusive; i++)
{ {
@ -136,7 +138,9 @@ namespace MathNet.Numerics.Threading
// fast forward execution in case parallelization is disabled // fast forward execution in case parallelization is disabled
// (cdrnet, 200908): should we fast forward on STA threads as well? // (cdrnet, 200908): should we fast forward on STA threads as well?
if (Control.DisableParallelization || ThreadQueue.ThreadCount <= 1) if (Control.DisableParallelization
|| ThreadQueue.ThreadCount <= 1
|| ThreadQueue.IsInWorkerThread)
{ {
for (int i = 0; i < actions.Length; i++) for (int i = 0; i < actions.Length; i++)
{ {

16
src/Numerics/Threading/ThreadQueue.cs

@ -77,6 +77,12 @@ namespace MathNet.Numerics.Threading
/// </summary> /// </summary>
internal static int ThreadCount { get; private set; } internal static int ThreadCount { get; private set; }
/// <summary>
/// Indicating whether the current thread is a parallelized worker thread.
/// </summary>
[ThreadStatic]
private static bool _isInWorkerThread;
/// <summary> /// <summary>
/// Initializes static members of the ThreadQueue class. /// Initializes static members of the ThreadQueue class.
/// </summary> /// </summary>
@ -85,6 +91,14 @@ namespace MathNet.Numerics.Threading
Start(Environment.ProcessorCount); Start(Environment.ProcessorCount);
} }
/// <summary>
/// Gets a value indicating whether the current thread is a parallelized worker thread.
/// </summary>
internal static bool IsInWorkerThread
{
get { return _isInWorkerThread; }
}
/// <summary> /// <summary>
/// Add a job to the queue. /// Add a job to the queue.
/// </summary> /// </summary>
@ -131,6 +145,8 @@ namespace MathNet.Numerics.Threading
/// </summary> /// </summary>
private static void WorkerThreadStart() private static void WorkerThreadStart()
{ {
_isInWorkerThread = true;
while (_running) while (_running)
{ {
// Wait until a job is available, or we should shut down // Wait until a job is available, or we should shut down

43
src/UnitTests/ThreadingTests/ParallelTest.cs

@ -143,5 +143,48 @@ namespace MathNet.Numerics.UnitTests.ThreadingTests
Assert.AreEqual(1001, items[i], i.ToString()); Assert.AreEqual(1001, items[i], i.ToString());
} }
} }
[Test, ApartmentState(ApartmentState.MTA)]
public void DoesDetectAndResolveRecursiveParallelization()
{
int countSharedBetweenClosures = 0;
Assert.DoesNotThrow(
() =>
Parallel.For(
0,
10,
j => Interlocked.Increment(ref countSharedBetweenClosures)));
Assert.AreEqual(10, countSharedBetweenClosures);
countSharedBetweenClosures = 0;
Parallel.For(
0,
10,
i =>
Parallel.For(
0,
10,
j => Interlocked.Increment(ref countSharedBetweenClosures)));
Assert.AreEqual(100, countSharedBetweenClosures);
countSharedBetweenClosures = 0;
Parallel.For(
0,
10,
i =>
Parallel.For(
0,
10,
j =>
Parallel.For(
0,
10,
k => Interlocked.Increment(ref countSharedBetweenClosures))));
Assert.AreEqual(1000, countSharedBetweenClosures);
}
} }
} }
Loading…
Cancel
Save