001    /*
002      Based on some code found with Google, somewhere in the Internet
003    
004      This program is free software; you can redistribute it and/or modify
005      it under the terms of the GNU Lesser General Public License as
006      published by the Free Software Foundation; either version 2 of the
007      License, or (at your option) any later version.
008    
009      This program is distributed in the hope that it will be useful,
010      but WITHOUT ANY WARRANTY; without even the implied warranty of
011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012      GNU Lesser General Public License for more details.
013    
014      You should have received a copy of the GNU Lesser General Public License
015      along with this program; if not, write to the Free Software
016      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
017    
018    package org.objectweb.jac.util;
019    
020    import org.apache.log4j.Logger;
021    
022    
023    
024    /**
025     * This is a simple implementation of the well-known semaphore synchronization feature.
026     *
027     * <p>It allows a given number of thread to be blocked waiting for a
028     * resource to be freed by the threads that are currently using it. */
029    
030    public class Semaphore {
031        static Logger logger = Logger.getLogger("semaphore");
032    
033        /** The available resources count. */ 
034        protected int count = 0;
035        private int waitingCount = 0;
036       
037        /**
038         * The semaphore constructor that allows the programmer to assign a
039         * number of resources item that are greater than 0 or 1 (meaning
040         * that several threads (n exactly) can use the semaphore at the
041         * same time).
042         * 
043         * @param n the number of resource items */
044    
045        public Semaphore(int n) { 
046            this.count = n; 
047        }
048    
049        /**
050         * The default constructor for this semaphore equivalent to
051         * <code>Semaphore(0)</code>.
052         *
053         * <p>This constructor means that no resources are available by
054         * default. Thus, the first thread (t1) that will acquire the
055         * semaphore will eventually by blocked until another thread (t2)
056         * releases a resource on this semaphore.
057         *
058         * <p>This use of the semaphore feature is quite strange regarding
059         * resources (since the deblocking thread (t2) releases a resource
060         * that it never acquired!!) but it can be very usefull for
061         * synchronization especially if t1 waits for a result that is
062         * being calculating by t2 and that is not yet available. */
063    
064        public Semaphore() {
065        }
066    
067        /**
068         * Gets the number of threads that are currently blocked on this
069         * semaphore.
070         *
071         * <p>This method is an indication but is not safe since a thread
072         * can be released meantime you evaluate its result.
073         *
074         * @return the waiting threads number at the moment you have asked
075         * it */
076    
077        public int getWaitingCount() {
078            return waitingCount;
079        }
080    
081        public int getCount() {
082            return count;
083        }
084    
085        /**
086         * Acquires a resource on this semaphore with no timeout.
087         *
088         * <p>If no resources are available anymore (count == 0), then the
089         * thread that performed this call is blocked until another thread
090         * releases a resource.</p>
091         *
092         * @return true if the resource could be aquired.
093         *
094         * @see #acquire(long)
095         * @see #release() 
096         */
097        public boolean acquire() {
098            return acquire(0);
099        }
100    
101        /**
102         * Acquires a resource on this semaphore.
103         *
104         * <p>If no resources are available anymore (count == 0), then the
105         * thread that performed this call is blocked until another thread
106         * releases a resource.
107         *
108         * @param timeout milliseconds to wait for. 0 means wait for ever.
109         * @return true if the resource could be aquired.
110         *
111         * @see #acquire()
112         * @see #release() 
113         */
114        public synchronized boolean acquire(long timeout) {
115            waitingCount++;
116            while(count == 0) {
117                logger.debug(this+" acquire, waiting;  count = "+count);
118                try {
119                    wait(timeout);
120                    // I think this is not correct in the general case but
121                    // should work if there's only on thread waiting.
122                    if (count==0) 
123                        return false;
124                } catch (InterruptedException e) {
125                    //keep trying
126                }
127            }
128            logger.debug(this+" acquired, count = "+count+"(--)");
129            count--;
130            waitingCount--;
131            return true;
132        }
133    
134        /**
135         * Releases a resource on this semaphore.
136         *
137         * <p>If one or several threads are blocked, waiting for a resource
138         * to be available, then this call will necessaraly makes one of
139         * them take the semaphore's monitor (the others, if any will block
140         * again). There is absolutly no way of knowing which thread will
141         * take the monitor first.
142         *
143         * @see #acquire() 
144         */
145        public synchronized void release() {
146            logger.debug(this+" release, count = "+count+"(++)");
147            count++;
148            notify(); //alert a thread that's blocking on this semaphore
149        }
150    }