// This is a wrapper class for java.util.concurrent.Semaphore. It provides acquire() // and release() methods that work as usual, but that also have the side-effect of // calling timeSim routines, so that timeSim can keep track of how many threads // are still computing at the current simulated time. public class Semaphore { java.util.concurrent.Semaphore s; // A semaphore from the Java concurrency package int semCounter; // This is the integer value of the semaphore. java.util.concurrent.Semaphore semMutex; // --------------- constructor ------------- Semaphore (int permit, boolean fifo) { s = new java.util.concurrent.Semaphore (permit, fifo); semCounter=permit; semMutex=new java.util.concurrent.Semaphore(1,true); } // --------------- acquire ------------------- void acquire() { try { semMutex.acquire(); } catch(Exception e){} if (semCounter >= 1) { // this threas is not going to be waiting semCounter--; try{ s.acquire(); } catch (Exception e){ System.out.println(e); } semMutex.release(); } else { // This thread will have to wait on the acquire. // Decrement semCounter before the acquire(), so that another thread // cannot jump in and sample semCounter when it is >= 1. semCounter--; semMutex.release(); Synch.timeSim.threadComputationDoneForNow(); try{ s.acquire(); } catch (Exception e){System.out.println(e);} } } // ----------------- release --------------- void release (){ try { semMutex.acquire(); } catch(Exception e){} if (semCounter < 0) { // semCounter is less than zero, so there are definitely threads waiting. // Call timesim to let it know that one thread will be woken up. Synch.timeSim.threadComputationStarting(); semCounter++; s.release(); } else { // No threads will be awakened. Just call release(). semCounter++; s.release(); } semMutex.release(); } }