-
Notifications
You must be signed in to change notification settings - Fork 0
/
SBParallelFor.cs
89 lines (77 loc) · 2.9 KB
/
SBParallelFor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
using System.Threading;
using System;
namespace SiegeBreaker
{
public class SBParallel
{
private class ParallelForRun : IDisposable
{
private volatile int m_nextUnitIndex;
private volatile int m_numFinishedUnits;
private int m_numUnits;
private int m_first;
private EventWaitHandle m_joinEvent;
ParallelForIterationDelegate m_iterationRun;
public ParallelForRun(int numUnits, int first, ParallelForIterationDelegate iterationRun)
{
m_first = first;
m_numUnits = numUnits;
m_iterationRun = iterationRun;
m_nextUnitIndex = 0;
m_numFinishedUnits = 0;
m_joinEvent = new EventWaitHandle(false, EventResetMode.AutoReset);
}
#pragma warning disable 0420 //a reference to a volatile field will not be treated as volatile
public void ThreadRunIterations()
{
int startedUnit = Interlocked.Increment(ref m_nextUnitIndex) - 1;
int finishedUnit = -1;
while (startedUnit < m_numUnits)
{
m_iterationRun(startedUnit + m_first);
finishedUnit = Interlocked.Increment(ref m_numFinishedUnits);
startedUnit = Interlocked.Increment(ref m_nextUnitIndex) - 1;
}
if (finishedUnit == m_numUnits)
m_joinEvent.Set();
}
#pragma warning restore 0420
public void Join()
{
m_joinEvent.WaitOne();
}
public void Dispose()
{
m_joinEvent.Close();
}
}
private class ParallelForJob : SBJob
{
private ParallelForRun loopRun;
public ParallelForJob(ParallelForRun loopRun)
{
this.loopRun = loopRun;
}
public sealed override void Run(SBThreadPool pool)
{
loopRun.ThreadRunIterations();
}
}
public delegate void ParallelForIterationDelegate(int index);
public static void For(SBThreadPool pool, int inclusiveStart, int exclusiveEnd, ParallelForIterationDelegate iterate)
{
if(inclusiveStart >= exclusiveEnd)
return;
using (ParallelForRun loopRun = new ParallelForRun(exclusiveEnd - inclusiveStart, inclusiveStart, iterate))
{
for (int i = 0; i < pool.NumThreads; i++)
{
SBJob job = new ParallelForJob(loopRun);
job.QueueInPool(pool);
}
loopRun.ThreadRunIterations();
loopRun.Join();
}
}
}
}