001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.lock.rw; 020 021import java.util.concurrent.TimeUnit; 022import java.util.concurrent.locks.Lock; 023import java.util.concurrent.locks.ReentrantReadWriteLock; 024 025import lucee.commons.lock.LockException; 026import lucee.commons.lock.LockInterruptedException; 027 028public class RWLock<L> { 029 030 private final ReentrantReadWriteLock rwl; 031 private final Lock rl; 032 private final Lock wl; 033 034 private L label; 035 private int count; 036 037 public RWLock(L label) { 038 rwl=new ReentrantReadWriteLock(true); 039 rl = rwl.readLock(); 040 wl = rwl.writeLock(); 041 this.label=label; 042 } 043 044 045 public void lock(long timeout, boolean readOnly) throws LockException, LockInterruptedException { 046 if(timeout<=0) throw new LockException("timeout must be a postive number"); 047 try { 048 if(!getLock(readOnly).tryLock(timeout, TimeUnit.MILLISECONDS)){ 049 throw new LockException(timeout); 050 } 051 } 052 catch (InterruptedException e) { 053 throw new LockInterruptedException(e); 054 } 055 } 056 057 synchronized void inc(){ 058 count++; 059 } 060 synchronized void dec(){ 061 count--; 062 } 063 064 065 public void unlock(boolean readOnly) { 066 //print.e("unlock:"+readOnly); 067 getLock(readOnly).unlock(); 068 } 069 070 private java.util.concurrent.locks.Lock getLock(boolean readOnly) { 071 return readOnly?rl:wl; 072 } 073 074 /** 075 * Returns an estimate of the number of threads waiting to 076 * acquire this lock. The value is only an estimate because the number of 077 * threads may change dynamically while this method traverses 078 * internal data structures. This method is designed for use in 079 * monitoring of the system state, not for synchronization 080 * control. 081 * 082 * @return the estimated number of threads waiting for this lock 083 */ 084 public int getQueueLength() { 085 return count; 086 } 087 088 /** 089 * Queries if the write lock is held by any thread. 090 */ 091 public boolean isWriteLocked(){ 092 return rwl.isWriteLocked(); 093 } 094 095 /** 096 * Queries if one or more write lock is held by any thread. 097 */ 098 public boolean isReadLocked(){ 099 return rwl.getReadLockCount()>0; 100 } 101 public L getLabel(){ 102 return label; 103 } 104}