-
Notifications
You must be signed in to change notification settings - Fork 0
/
Smoker.cs
104 lines (94 loc) · 4.16 KB
/
Smoker.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using ThreadSupport = TestConcurrencyUtilities.TestSupport;
using System.Collections.Generic;
using ConcurrencyUtilities;
namespace CigaretteSmokers
{
/// <summary>
/// The smoker. Runs the problem solution.
/// </summary>
public class Smoker
{
public string Name { get; private set; } // The name of the smoker (indicating the unlimited resource held)
Table _table; // The 'agent' table
List<SmokerResource> _resourcesNeeded; // The list of the two resources that this smoker needs
int _greedyTime; // The time duration that should be spent smoking before telling the agent to restock
IterationManager _iterationManager; /* The iteration manager for the 'Resource turnstiling and
iteration checking' solution */
/// <summary>
/// Initializes a new instance of the <see cref="CigaretteSmokers.Smoker"/> class.
/// </summary>
/// <param name="name">The name of the smoker (indicating the unlimited resource held).</param>
/// <param name="resourcesNeeded">The list of the two resources that this smoker needs.</param>
/// <param name="table">The 'agent' table.</param>
/// <param name="iterationManager">The iteration manager for the 'Resource turnstiling and
/// iteration checking' solution.</param>
/// <param name="greedyTime">The time duration that should be spent smoking before telling the agent to
/// restock.</param>
public Smoker(string name, List<SmokerResource> resourcesNeeded, Table table,
IterationManager iterationManager, int greedyTime = 0) {
Name = name;
_table = table;
_resourcesNeeded = resourcesNeeded;
_iterationManager = iterationManager;
_greedyTime = greedyTime;
}
/// <summary>
/// Runs the smoker, demonstrating the problem issue.
/// </summary>
public void RunIssueDemonstration() {
while (true) {
foreach (SmokerResource r in _resourcesNeeded) {
ThreadSupport.DebugThread("{yellow}Acquiring: " + r.Name + "...");
r.Take();
ThreadSupport.DebugThread("{green}Acquired: " + r.Name);
}
ThreadSupport.DebugThread("{green}Smoking");
ThreadSupport.SleepThread(_greedyTime);
_table.ReadyToStartNewIteration();
}
}
/// <summary>
/// Runs the smoker, using my own 'Resource turnstiling and iteration checking' solution.
/// I'm a bit proud of this =)
/// </summary>
public void RunSolutionByResourceTurnstilingAndIterationChecking() {
while (true) {
// Remember the iteration ID from before we start checking for our required resources
_iterationManager.AccessToIterationID.Acquire();
Object iterIDAtStart = _iterationManager.IterationID;
_iterationManager.AccessToIterationID.Release();
// Check for the first required resource
_resourcesNeeded[0].Take();
_resourcesNeeded[0].Return();
// Check that we're still on the same iteration. If not, start again
if (_iterationManager.IterationID == iterIDAtStart) { // No need to acquire permission; not critical
// Check for the second required resource
_resourcesNeeded[1].Take();
_resourcesNeeded[1].Return();
// Check that we're still on the same iteration. If not, start again
bool successfullyAcquiredResourcesNeeded = false;
_iterationManager.AccessToIterationID.Acquire(); // Need to acquire permission for final verification
if (_iterationManager.IterationID == iterIDAtStart) {
/* Both resources are available, and it's still the same iteration as when we started, so
acquire the resources we need */
successfullyAcquiredResourcesNeeded = true;
foreach (SmokerResource r in _resourcesNeeded) {
r.Take();
ThreadSupport.DebugThread("{black}Acquired: " + r.Name);
}
}
_iterationManager.AccessToIterationID.Release();
// Now that we're outside the iteration ID access lock, check again that we were successful
if (successfullyAcquiredResourcesNeeded) {
// The resources have been acquired successfully, so commence smoking!
ThreadSupport.DebugThread("{green}Smoking");
ThreadSupport.SleepThread(_greedyTime);
_iterationManager.NewIteration(); // Update the iteration ID for a new iteration
// You'd do any actual work now
}
}
}
}
}
}