/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 */
package fr.gouv.culture.util.apache.avalon.excalibur.concurrent;

/*MAJ_COCOON_2.1.10
import org.apache.avalon.excalibur.concurrent.Sync;*/
import EDU.oswego.cs.dl.util.concurrent.Sync;

/**
 *
 * @version CVS $Revision: 1.1 $ $Date: 2007/09/19 15:51:11 $
 * @since 4.0
 */

public class Semaphore
        implements Sync {
    private long max_tokens;
    private long m_tokens;

    public Semaphore(final long tokens) {
        max_tokens = tokens;
        m_tokens = max_tokens;
    }

    public synchronized void acquire()
            throws InterruptedException {
        //TODO: check for interuption outside sync block?
        if (Thread.interrupted()) throw new InterruptedException();

        //While there is no more tokens left wait
        while (0 >= m_tokens) {
            wait();
        }
        m_tokens--;
    }

    public synchronized void release() {
        if (m_tokens < max_tokens) {
            m_tokens++;
            notifyAll();
        }
    }

    public synchronized boolean attempt(final long msecs)
            throws InterruptedException {
        if (Thread.interrupted()) throw new InterruptedException();

        if (m_tokens > 0) {
            m_tokens--;
            return true;
        } else {
            final long start = System.currentTimeMillis();
            long wait = msecs;

            while (wait > 0) {
                wait(wait);

                if (m_tokens > 0) {
                    m_tokens--;
                    return true;
                } else {
                    wait = msecs - (System.currentTimeMillis() - start);
                }
            }

            return false;
        }
    }

    public long getTokens() {
        return m_tokens;
    }
}
