001    package railo.commons.lock.rw;
002    
003    import java.util.concurrent.TimeUnit;
004    import java.util.concurrent.locks.Lock;
005    import java.util.concurrent.locks.ReentrantReadWriteLock;
006    
007    import railo.commons.lock.LockException;
008    import railo.commons.lock.LockInterruptedException;
009    
010    public class RWLock<L> {
011            
012            private final ReentrantReadWriteLock rwl;
013            private final Lock rl;
014        private final Lock wl;
015    
016            private L label;
017            private int count;
018            
019            public RWLock(L label) {
020                    rwl=new ReentrantReadWriteLock(true);
021                    rl = rwl.readLock();
022                wl = rwl.writeLock();
023                    this.label=label;
024            }
025    
026            
027            public void lock(long timeout, boolean readOnly) throws LockException, LockInterruptedException {
028                    if(timeout<=0) throw new LockException("timeout must be a postive number");
029                    try {
030                            if(!getLock(readOnly).tryLock(timeout, TimeUnit.MILLISECONDS)){
031                                    throw new LockException(timeout);
032                            }
033                    } 
034                    catch (InterruptedException e) {
035                            throw new LockInterruptedException(e);
036                    }
037            }
038    
039            synchronized void inc(){
040                    count++;
041            }
042            synchronized void dec(){
043                    count--;
044            }
045    
046    
047            public void unlock(boolean readOnly)    {
048                    //print.e("unlock:"+readOnly);
049                    getLock(readOnly).unlock();
050            }
051    
052            private java.util.concurrent.locks.Lock getLock(boolean readOnly) {
053                    return readOnly?rl:wl;
054            }
055            
056            /**
057         * Returns an estimate of the number of threads waiting to
058         * acquire this lock.  The value is only an estimate because the number of
059         * threads may change dynamically while this method traverses
060         * internal data structures.  This method is designed for use in
061         * monitoring of the system state, not for synchronization
062         * control.
063         *
064         * @return the estimated number of threads waiting for this lock
065         */
066        public int getQueueLength() {
067                    return count;
068            }
069        
070    
071            public L getLabel(){
072                    return label;
073            }
074    }