Source for org.jfree.threads.ReaderWriterLock

   1: /* ========================================================================
   2:  * JCommon : a free general purpose class library for the Java(tm) platform
   3:  * ========================================================================
   4:  *
   5:  * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
   6:  * 
   7:  * Project Info:  http://www.jfree.org/jcommon/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  * 
  27:  * ---------------------
  28:  * ReaderWriterLock.java
  29:  * ---------------------
  30:  *
  31:  * $Id: ReaderWriterLock.java,v 1.3 2005/10/18 13:18:34 mungady Exp $
  32:  *
  33:  * Changes
  34:  * -------
  35:  * 29-Jan-2003 : Added standard header (DG);
  36:  *
  37:  */
  38: 
  39: package org.jfree.threads;
  40: 
  41: import java.util.ArrayList;
  42: import java.util.Iterator;
  43: 
  44: /**
  45:  * A reader-writer lock from "Java Threads" by Scott Oak and Henry Wong.
  46:  *
  47:  * @author Scott Oak and Henry Wong
  48:  */
  49: public class ReaderWriterLock {
  50: 
  51:     /**
  52:      * A node for the waiting list.
  53:      *
  54:      * @author Scott Oak and Henry Wong
  55:      */
  56:     private static class ReaderWriterNode {
  57: 
  58:         /** A reader. */
  59:         protected static final int READER = 0;
  60: 
  61:         /** A writer. */
  62:         protected static final int WRITER = 1;
  63: 
  64:         /** The thread. */
  65:         protected Thread t;
  66: 
  67:         /** The state. */
  68:         protected int state;
  69: 
  70:         /** The number of acquires.*/
  71:         protected int nAcquires;
  72: 
  73:         /**
  74:          * Creates a new node.
  75:          *
  76:          * @param t  the thread.
  77:          * @param state  the state.
  78:          */
  79:         private ReaderWriterNode(final Thread t, final int state) {
  80:             this.t = t;
  81:             this.state = state;
  82:             this.nAcquires = 0;
  83:         }
  84: 
  85:     }
  86: 
  87:     /** The waiting threads. */
  88:     private ArrayList waiters;
  89: 
  90:     /**
  91:      * Default constructor.
  92:      */
  93:     public ReaderWriterLock() {
  94:         this.waiters = new ArrayList();
  95:     }
  96: 
  97:     /**
  98:      * Grab the read lock.
  99:      */
 100:     public synchronized void lockRead() {
 101:         final ReaderWriterNode node;
 102:         final Thread me = Thread.currentThread();
 103:         final int index = getIndex(me);
 104:         if (index == -1) {
 105:             node = new ReaderWriterNode(me, ReaderWriterNode.READER);
 106:             this.waiters.add(node);
 107:         }
 108:         else {
 109:             node = (ReaderWriterNode) this.waiters.get(index);
 110:         }
 111:         while (getIndex(me) > firstWriter()) {
 112:             try {
 113:                 wait();
 114:             }
 115:             catch (Exception e) {
 116:                 System.err.println("ReaderWriterLock.lockRead(): exception.");
 117:                 System.err.print(e.getMessage());
 118:             }
 119:         }
 120:         node.nAcquires++;
 121:     }
 122: 
 123:     /**
 124:      * Grab the write lock.
 125:      */
 126:     public synchronized void lockWrite() {
 127:         final ReaderWriterNode node;
 128:         final Thread me = Thread.currentThread();
 129:         final int index = getIndex(me);
 130:         if (index == -1) {
 131:             node = new ReaderWriterNode(me, ReaderWriterNode.WRITER);
 132:             this.waiters.add(node);
 133:         }
 134:         else {
 135:             node = (ReaderWriterNode) this.waiters.get(index);
 136:             if (node.state == ReaderWriterNode.READER) {
 137:                 throw new IllegalArgumentException("Upgrade lock");
 138:             }
 139:             node.state = ReaderWriterNode.WRITER;
 140:         }
 141:         while (getIndex(me) != 0) {
 142:             try {
 143:                 wait();
 144:             }
 145:             catch (Exception e) {
 146:                 System.err.println("ReaderWriterLock.lockWrite(): exception.");
 147:                 System.err.print(e.getMessage());
 148:             }
 149:         }
 150:         node.nAcquires++;
 151:     }
 152: 
 153:     /**
 154:      * Unlock.
 155:      */
 156:     public synchronized void unlock() {
 157: 
 158:         final ReaderWriterNode node;
 159:         final Thread me = Thread.currentThread();
 160:         final int index = getIndex(me);
 161:         if (index > firstWriter()) {
 162:             throw new IllegalArgumentException("Lock not held");
 163:         }
 164:         node = (ReaderWriterNode) this.waiters.get(index);
 165:         node.nAcquires--;
 166:         if (node.nAcquires == 0) {
 167:             this.waiters.remove(index);
 168:         }
 169:         notifyAll();
 170:     }
 171: 
 172:     /**
 173:      * Returns the index of the first waiting writer.
 174:      *
 175:      * @return The index.
 176:      */
 177:     private int firstWriter() {
 178:         final Iterator e = this.waiters.iterator();
 179:         int index = 0;
 180:         while (e.hasNext()) {
 181:             final ReaderWriterNode node = (ReaderWriterNode) e.next();
 182:             if (node.state == ReaderWriterNode.WRITER) {
 183:                 return index;
 184:             }
 185:             index += 1;
 186:         }
 187:         return Integer.MAX_VALUE;
 188:     }
 189: 
 190:     /**
 191:      * Returns the index of a thread.
 192:      *
 193:      * @param t  the thread.
 194:      *
 195:      * @return The index.
 196:      */
 197:     private int getIndex(final Thread t) {
 198:         final Iterator e = this.waiters.iterator();
 199:         int index = 0;
 200:         while (e.hasNext()) {
 201:             final ReaderWriterNode node = (ReaderWriterNode) e.next();
 202:             if (node.t == t) {
 203:                 return index;
 204:             }
 205:             index += 1;
 206:         }
 207:         return -1;
 208:     }
 209: 
 210: }