Source code: com/yaftp/utils/TokenSemaphore.java
1 /**
2 *
3 * CopyRights Jean-Yves MENGANT 1999,2000,2001,2002
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 package com.yaftp.utils;
21
22 /**
23
24 Copyright Jean-Yves MENGANT 1998,1999,2000
25
26 This class implements a MUTUAL EXCLUSIVE semaphore
27 access using internal _tokenIsReady flag
28 use this to synchronize concurent access to a single
29 ressource
30
31 Implementation is based on OReilly JAVA THREAD book examples
32
33 @author Jean-Yves MENGANT
34
35 */
36
37 public class TokenSemaphore {
38
39 transient private int _busyCount = 0 ;
40 transient private Thread _owner = null ;
41 transient private String _name ;
42 transient private boolean _debug = false ;
43
44 public final static boolean _SET_BUSY_ = true ;
45 public final static boolean _SET_FREE_ = false ;
46
47 public final static boolean _DEBUG_MODE_ = true ;
48
49 public void set_debug( boolean debug )
50 { _debug = debug ; }
51
52 private void debug( String dbg )
53 {
54 System.out.println( Thread.currentThread() + dbg ) ;
55 }
56
57 private void initInstance( String name ,
58 boolean tokenState
59 )
60 {
61 // if ( _debug )
62 // debug("entering construction for : "+name+this) ;
63
64 _name = name ;
65
66 if ( tokenState ) // if true => owning Token is requested by thread
67 waitForSemaphore() ;
68
69 // if ( _debug )
70 // debug("leaving construction for : "+name+this) ;
71 }
72
73 /** basic constructor */
74 public TokenSemaphore( String name ,
75 boolean tokenState
76 )
77 {
78 initInstance(name,tokenState) ;
79 }
80
81 /** debug Constructor */
82 public TokenSemaphore( String name ,
83 boolean tokenState ,
84 boolean debug
85 )
86 {
87 set_debug(debug) ;
88 initInstance(name,tokenState) ;
89 }
90
91 private synchronized Thread getBusyCountOwner()
92 {
93 return _owner ;
94 }
95
96 /** request token primitive */
97 private synchronized boolean tryGetToken()
98 {
99 // if ( _debug )
100 // debug("entering TryGetToken") ;
101
102 if ( _owner == null )
103 {
104 // if ( _debug )
105 // debug( " will Own "+ _name + "." + this ) ;
106 _owner = Thread.currentThread() ;
107 _busyCount = 1 ;
108 return true ;
109 }
110
111 if ( _owner == Thread.currentThread() )
112 {
113 _busyCount++ ;
114
115 // if ( _debug )
116 // debug( " increments counter " + _busyCount
117 // + " on " + _name + "." + this ) ;
118 return true ;
119 }
120
121 // if ( _debug )
122 // debug( " " + this + " is owned by : " + _owner ) ;
123
124 // if ( _debug )
125 // debug(" leaving TryGetToken : nothing done") ;
126
127 return false ;
128 }
129
130 /** wait for synchronized ressource */
131 public synchronized void waitForSemaphore()
132 {
133 // if ( _debug )
134 // debug( " waits for sem on : " + _name + "." + this ) ;
135
136 while ( tryGetToken() == false )
137 try {
138 // if ( _debug )
139 // debug( " before wait()") ;
140
141 wait() ;
142
143 // if ( _debug )
144 // debug( " END OF WAIT for :"+this) ;
145 } catch ( InterruptedException e ){}
146
147 // if ( _debug )
148 // debug( " leaving waitForSem") ;
149 }
150
151 /** free synchronized ressource */
152 public synchronized void freeSemaphore()
153 {
154 // if ( _debug )
155 // debug( " entering freeSemaphore") ;
156
157 if ( getBusyCountOwner() == Thread.currentThread() )
158 {
159 // if ( _debug )
160 // debug( " decrements counter " + _busyCount ) ;
161 _busyCount-- ;
162 if ( _busyCount == 0 )
163 {
164 _owner = null ;
165 // if ( _debug )
166 // debug(" NO MORE OWNING : "+ _name + "." + this ) ;
167 notify() ;
168 }
169 }
170 // else
171 // if ( _debug )
172 // debug( " NOT FREED owner is : " + _owner ) ;
173
174 // if ( _debug )
175 // debug( " leaving freeSemaphore") ;
176 }
177
178 /**
179 put a clean waiting process when a thread is
180 waiting upon another thread getting ressource
181 property
182 */
183 public void waitForOwning( Thread owner )
184 {
185 // if ( _debug )
186 // debug( " waiting for "
187 // + owner + " to own instead of "
188 // + _owner
189 // ) ;
190
191 while ( getBusyCountOwner() != owner )
192 {
193 Thread.yield() ;
194 try {
195 Thread.sleep(1) ;
196 } catch ( InterruptedException e ){} ;
197 }
198
199 // if ( _debug )
200 // debug( " leaving waitforOwning " );
201 }
202
203 /** returns true if object is belonging to some thread */
204 public synchronized boolean isBusy ()
205 { return ( _owner != null ) ; }
206
207 /**
208 Unit Testing semaphores
209 */
210 public static void main ( String arg[] )
211 {
212 RunnerWaiter runwait = new RunnerWaiter() ;
213
214
215 _PRIMARY_ primary = new _PRIMARY_ (runwait) ;
216 _SECONDARY_ secondary = new _SECONDARY_(runwait) ;
217
218 primary.start() ;
219 secondary.start() ;
220 }
221 }
222
223 // internal unit test classes
224 // The primary
225 class _PRIMARY_ extends Thread {
226 RunnerWaiter _cur ;
227 long _count = 0 ;
228
229 public _PRIMARY_( RunnerWaiter cur )
230 { super("_PRIMARY_") ;
231 _cur = cur ;
232 }
233
234 public void run()
235 {
236 long testNum = 0 ;
237 System.out.println("PRIMARY started") ;
238 while ( true )
239 {
240 _cur.startRUNNER() ;
241
242 System.out.println( Thread.currentThread().getName() +
243 "ENTERING RUNNER :" + _count +
244 " memory : " +
245 Runtime.getRuntime().freeMemory() ) ;
246 _count++ ;
247 for (int ii = 1 ; ii < 100 ; ii++ ) ;
248 try {
249 Thread.sleep(100) ;
250 } catch ( InterruptedException e ) {}
251
252
253 _cur.stopRUNNER() ;
254 }
255 }
256 } ;
257
258 class _SECONDARY_ extends Thread {
259 RunnerWaiter _cur ;
260 long _count = 0 ;
261
262 public _SECONDARY_( RunnerWaiter cur )
263 { super("_SECONDARY_") ;
264 _cur = cur ;
265 }
266
267 public void run()
268 {
269 long testNum = 0 ;
270 System.out.println("SECONDARY started") ;
271 while ( true )
272 {
273 _cur.startWAITER() ;
274
275 System.out.println( Thread.currentThread().getName() +
276 "ENTERING WAITER count :" + _count +
277 " memory : " +
278 Runtime.getRuntime().freeMemory()
279 ) ;
280 _count++ ;
281 for (int ii = 1 ; ii < 100000 ; ii++ ) ;
282
283 _cur.stopWAITER() ;
284 }
285 }
286 } ;