/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
**/
package lucee.commons.lock.rw;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import lucee.commons.lock.LockException;
import lucee.commons.lock.LockInterruptedException;
public class RWLock<L> {
private final ReentrantReadWriteLock rwl;
private final Lock rl;
private final Lock wl;
private L label;
private int count;
public RWLock(L label) {
rwl=new ReentrantReadWriteLock(true);
rl = rwl.readLock();
wl = rwl.writeLock();
this.label=label;
}
public void lock(long timeout, boolean readOnly) throws LockException, LockInterruptedException {
if(timeout<=0) throw new LockException("timeout must be a postive number");
try {
if(!getLock(readOnly).tryLock(timeout, TimeUnit.MILLISECONDS)){
throw new LockException(timeout);
}
}
catch (InterruptedException e) {
throw new LockInterruptedException(e);
}
}
synchronized void inc(){
count++;
}
synchronized void dec(){
count--;
}
public void unlock(boolean readOnly) {
//print.e("unlock:"+readOnly);
getLock(readOnly).unlock();
}
private java.util.concurrent.locks.Lock getLock(boolean readOnly) {
return readOnly?rl:wl;
}
/**
* Returns an estimate of the number of threads waiting to
* acquire this lock. The value is only an estimate because the number of
* threads may change dynamically while this method traverses
* internal data structures. This method is designed for use in
* monitoring of the system state, not for synchronization
* control.
*
* @return the estimated number of threads waiting for this lock
*/
public int getQueueLength() {
return count;
}
/**
* Queries if the write lock is held by any thread.
*/
public boolean isWriteLocked(){
return rwl.isWriteLocked();
}
/**
* Queries if one or more write lock is held by any thread.
*/
public boolean isReadLocked(){
return rwl.getReadLockCount()>0;
}
public L getLabel(){
return label;
}
}