/*
* Class CountSem
*
* This software is developed for Choral devices with Java.
* Copyright Choral srl. All Rights reserved.
*/
package general;
/**
* SemaforoEV extension, provides the ability to request / provide
* a number of "tokens" different from 1
*
* @version 1.00 <BR> <i>Last update</i>: 06-07-2007
* @author alessioza
*
*/
public class CountSem extends SemaforoEV {
/*
* constructors
*/
public CountSem(int v, boolean fifo) {
super(v, v==0 ? 1 : v, fifo); // max is irrelevant
}
public CountSem(int v) {
this(v, true);
}
/*
* methods
*/
public synchronized void getCoin(int qty) { // REQUESTED 'qty' "TOKENS"
Thread curTh = Thread.currentThread();
if (value < qty) {
/* If al least 'qty' tokens are available, stop thread
* execution and add to queue */
waitNum++;
if(isFifo) { // add to FIFO queue
codaAttesa.addElement(new WaitingThread(curTh, false, qty));
} else { // add to LIFO head (position 0)
codaAttesa.insertElementAt(new WaitingThread(curTh, false, qty), 0);
}
//System.out.println("GET: put "+curTh.getName()+"to queue");
//System.out.println("GET: number of threads in queue is: "+waitNum);
while(true) {
try {
wait();
} catch (InterruptedException ie) {
} //catch
/* if you have to awaken this thread,
* it isn't in general the first of the queue */
for (int i=0; i<codaAttesa.size(); i++) {
WaitingThread wt = (WaitingThread)codaAttesa.elementAt(i);
if (wt.th == curTh) {
// if I find the current thread...
if (wt.wakenUp) {
// and was awakened...
////System.out.println("GET: "+curTh.getName()+" has been awakened, I remove it from the queue");
codaAttesa.removeElementAt(i);
waitNum--;
/* the value of the semaphore is already OK */
return;
} else break; /* not to awaken, re-suspend */
} //if wt.th
else;
} //for
} //while
} else {
value -= qty; /* decreases semaphore of 'qty' quantity */
//System.out.println("GET: I can execute thread "+curTh.getName()+" immediately");
} //if value
//System.out.println("GET: Semaphore value is now: "+value);
//System.out.println("GET: Number of thread in the queue: "+waitNum);
} //getCoin(int qty)
public synchronized void putCoin(int qty) { // SUPPLY of 'qty' "TOKENS"
value += qty; // increase semaphore
if (waitNum > 0) {
// if there are waiting threads, tries to satisfy them immediately
//System.out.println("PUT: There are threads in the queue");
while(true) {
/* Search for the first thread (among those suspended and not satisfied)
* having the maximum of the required quantity (<= value) */
int maxReq = 0;
int found = -1; // index of Thread to da awaken
for (int i=0; i<codaAttesa.size(); i++) {
WaitingThread wt = (WaitingThread)codaAttesa.elementAt(i);
if (!wt.wakenUp && wt.qty <= value && wt.qty > maxReq) {
/* If thread has NOT been awakened yet and satify
* requirements, then I can awaken it */
found = i; // found a thread to awaken
maxReq = wt.qty;
} //if !wt.wakenUp...ecc
} //for
if (found == -1) {
// not found another thread to awaken
return;
} //if found
value = value - maxReq;
// decreased semaphore of the amount required by the awakened thread
//System.out.println("PUT: I prepare thread for awakening");
((WaitingThread)codaAttesa.elementAt(found)).wakenUp = true;
//System.out.println("PUT: notify to all threads");
notifyAll();
} //while
} //if waitNum
//System.out.println("PUT: Semaphore value is now: "+value);
//System.out.println("PUT: Number of thread in the queue: "+waitNum);
} //putCoin(int qty)
public synchronized void putCoin() { // delete quntity checking
putCoin(1);
} //putCoin()
} //CountSem