package it.yup.ui; public class Semaphore { /** current number of available permits **/ protected long permits_; /** * Create a Semaphore with the given initial number of permits. * Using a seed of one makes the semaphore act as a mutual exclusion lock. * Negative seeds are also allowed, in which case no acquires will proceed * until the number of releases has pushed the number of permits past 0. **/ public Semaphore(long initialPermits) { permits_ = initialPermits; } /** Wait until a permit is available, and take one **/ public void acquire() throws InterruptedException { synchronized (this) { try { while (permits_ <= 0) wait(); --permits_; } catch (InterruptedException ex) { notify(); throw ex; } } } /** Wait at most msecs millisconds for a permit. **/ public boolean attempt(long msecs) throws InterruptedException { synchronized (this) { if (permits_ > 0) { --permits_; return true; } else if (msecs <= 0) return false; else { try { long startTime = System.currentTimeMillis(); long waitTime = msecs; for (;;) { wait(waitTime); if (permits_ > 0) { --permits_; return true; } else { waitTime = msecs - (System.currentTimeMillis() - startTime); if (waitTime <= 0) return false; } } } catch (InterruptedException ex) { notify(); throw ex; } } } } /** Release a permit **/ public synchronized void release() { ++permits_; notify(); } /** * Release N permits. <code>release(n)</code> is * equivalent in effect to: * <pre> * for (int i = 0; i < n; ++i) release(); * </pre> * <p> * But may be more efficient in some semaphore implementations. * @exception IllegalArgumentException if n is negative. **/ public synchronized void release(long n) { if (n < 0) throw new IllegalArgumentException("Negative argument"); permits_ += n; for (long i = 0; i < n; ++i) notify(); } /** * Return the current number of available permits. * Returns an accurate, but possibly unstable value, * that may change immediately after returning. **/ public synchronized long permits() { return permits_; } }