forked from nmcl/JavaSim
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSemaphore.java
More file actions
159 lines (131 loc) · 4.01 KB
/
Semaphore.java
File metadata and controls
159 lines (131 loc) · 4.01 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
* Copyright 1990-2008, Mark Little, University of Newcastle upon Tyne
* and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 1990-2008,
*/
package org.javasim;
/**
* Classic semaphores can "accumulate" more resources than the starting
* value. The ceiling parameter is used to indicate whether or not the
* resource count should ever go beyond the initial value - the default
* is that it should.
*/
public class Semaphore
{
enum Outcome { DONE, NOTDONE, WOULD_BLOCK };
/**
* Create a new mutex (resources = 1).
*/
public Semaphore()
{
numberWaiting = 0;
numberOfResources = 1;
currentResources = 1;
}
/**
* Create a new semaphore (resources = number).
*
* @param number the number of resources.
*/
public Semaphore(long number)
{
numberWaiting = 0;
numberOfResources = number;
currentResources = number;
}
public void finalize ()
{
if (numberWaiting != 0)
System.out
.println("Warning: semaphore being removed with clients waiting.");
}
/**
* Number of entities blocked on the semaphore.
*
* @return the number of entities blocked.
*/
public synchronized long numberWaiting ()
{
return numberWaiting;
}
/**
* Try to acquire the semaphore. Caller will be blocked if there are no free
* resources.
*
* @param toWait the entity that will be blocked.
* @return an indication of the outcome.
* @throws RestartException if a reset occurs while an entity is blocked.
*/
public synchronized Outcome get (SimulationEntity toWait)
throws RestartException
{
if (currentResources > 0)
currentResources--;
else
{
numberWaiting++;
try
{
waitingList.insert(toWait);
}
catch (SimulationException e)
{
}
toWait.cancel();
}
return Outcome.DONE;
}
/**
* Only acquire the semaphore if it would not block the caller.
*
* @param toWait the entity to block.
* @return the outcome
*/
public synchronized Outcome tryGet (SimulationEntity toWait)
throws RestartException
{
if (currentResources == 0)
return Outcome.WOULD_BLOCK;
else
return get(toWait);
}
/**
* Release the semaphore. No check is made to ensure the caller has
* previously acquired the semaphore.
*
* @return the outcome
*/
public synchronized Outcome release ()
{
if (numberWaiting > 0)
{
currentResources++;
if (currentResources > numberOfResources)
currentResources = numberOfResources;
numberWaiting--;
// don't set trigger flag - not strictly a trigger
waitingList.triggerFirst(false);
return Outcome.DONE;
}
else
return Outcome.NOTDONE;
}
private TriggerQueue waitingList;
private long numberWaiting;
private long numberOfResources;
private long currentResources;
}