Skip to content
This repository was archived by the owner on Dec 22, 2019. It is now read-only.

Commit 3293b1e

Browse files
committed
Fixed deadlock bug in WorkerScheduler
1 parent c032313 commit 3293b1e

3 files changed

Lines changed: 63 additions & 12 deletions

File tree

UpdateLib/UpdateLib/Tasks/WorkerScheduler.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ public static WorkerScheduler Instance
3636

3737
private readonly long MAX_WORKERS;
3838
private readonly ConcurrentQueue<AsyncTask> m_taskQueue;
39-
private long m_currentWorkerCount;
39+
private readonly AtomicInteger m_currentWorkerCount;
4040
private readonly AsyncTask m_dispatcherTask;
41-
private ManualResetEvent m_waitForAvailableWorker;
41+
private readonly ManualResetEvent m_waitForAvailableWorker;
4242

4343
#endregion
4444

@@ -48,6 +48,7 @@ private WorkerScheduler()
4848
m_taskQueue = new ConcurrentQueue<AsyncTask>();
4949
m_dispatcherTask = AsyncTaskFactory.From(new Action(Dispatcher), null);
5050
m_waitForAvailableWorker = new ManualResetEvent(true);
51+
m_currentWorkerCount = new AtomicInteger();
5152
}
5253

5354
public void Schedule(AsyncTask task)
@@ -67,18 +68,14 @@ private void Dispatcher()
6768
if (task.IsCompleted || task.IsCancelled || task.HasErrors)
6869
continue;
6970

70-
if (m_currentWorkerCount >= MAX_WORKERS)
71-
m_waitForAvailableWorker.Reset();
72-
73-
m_waitForAvailableWorker.WaitOne();
74-
7571
SetupTask(task);
7672

77-
m_currentWorkerCount++;
78-
if (m_currentWorkerCount >= MAX_WORKERS)
73+
if (m_currentWorkerCount.Value >= MAX_WORKERS)
7974
m_waitForAvailableWorker.Reset();
8075

81-
Logger.Debug(GetType().Name, $"Current worker count: {m_currentWorkerCount}");
76+
m_waitForAvailableWorker.WaitOne();
77+
78+
Logger.Debug(GetType().Name, $"Current worker count: {m_currentWorkerCount.Increment()}");
8279

8380
task.ConfigureAwait(false).Start();
8481
}
@@ -88,8 +85,8 @@ private void SetupTask(AsyncTask task)
8885
{
8986
task.TaskCompleted += (o, e) =>
9087
{
91-
m_currentWorkerCount--;
92-
if (m_currentWorkerCount < MAX_WORKERS)
88+
89+
if (m_currentWorkerCount.Decrement() < MAX_WORKERS)
9390
m_waitForAvailableWorker.Set();
9491

9592
Logger.Debug(GetType().Name, $"Current worker count: {m_currentWorkerCount}");
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace MatthiWare.UpdateLib.Threading
7+
{
8+
public class AtomicInteger
9+
{
10+
private int m_value;
11+
private readonly object sync = new object();
12+
13+
public int Value
14+
{
15+
get
16+
{
17+
lock (sync)
18+
return m_value;
19+
}
20+
set
21+
{
22+
lock (sync)
23+
m_value = value;
24+
}
25+
}
26+
27+
public AtomicInteger()
28+
: this(0)
29+
{ }
30+
31+
public AtomicInteger(int startingValue)
32+
{
33+
m_value = startingValue;
34+
}
35+
36+
public int Increment()
37+
{
38+
lock (sync)
39+
return ++m_value;
40+
}
41+
42+
public int Decrement()
43+
{
44+
lock (sync)
45+
return --m_value;
46+
}
47+
48+
public override string ToString()
49+
{
50+
return Value.ToString();
51+
}
52+
}
53+
}

UpdateLib/UpdateLib/UpdateLib.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
</Compile>
8585
<Compile Include="Tasks\UpdateCacheTask.cs" />
8686
<Compile Include="Tasks\WorkerScheduler.cs" />
87+
<Compile Include="Threading\AtomicInteger.cs" />
8788
<Compile Include="Threading\ConcurrentQueue.cs" />
8889
<Compile Include="UI\Components\ChangelogPage.cs">
8990
<SubType>UserControl</SubType>

0 commit comments

Comments
 (0)