001: /*
002: * ReadWriteLock.java
003: *
004: * Copyright (C) 2002 Peter Graves
005: * $Id: ReadWriteLock.java,v 1.3 2002/10/06 23:59:46 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: public final class ReadWriteLock {
025: private int activeReaders;
026: private int activeWriters;
027: private int waitingReaders;
028: private int waitingWriters;
029: private Thread writerThread;
030: private int lockCount;
031:
032: public synchronized void lockRead() throws InterruptedException {
033: if (activeReaders != 0 || allowRead()) {
034: ++activeReaders;
035: return;
036: }
037: // Reaching here, either a write is in progress or waitingWriters > 0.
038: // If the current thread holds the write lock, we'll deadlock.
039: if (Thread.currentThread() == writerThread)
040: Debug.bug();
041: ++waitingReaders;
042: while (!allowRead()) {
043: try {
044: wait();
045: } catch (InterruptedException e) {
046: --waitingReaders; // Roll back state.
047: throw e;
048: }
049: }
050: --waitingReaders;
051: ++activeReaders;
052: }
053:
054: public synchronized void unlockRead() {
055: Debug.assertTrue(activeReaders > 0);
056: --activeReaders;
057: notifyAll();
058: }
059:
060: public synchronized void lockWrite() throws InterruptedException {
061: if (writerThread != null) {
062: // Write in progress.
063: if (Thread.currentThread() == writerThread) {
064: // Same thread.
065: ++lockCount;
066: return;
067: }
068: }
069: if (allowWrite()) {
070: claimWriteLock();
071: return;
072: }
073: ++waitingWriters;
074: while (!allowWrite()) {
075: try {
076: wait();
077: } catch (InterruptedException e) {
078: --waitingWriters;
079: throw e;
080: }
081: }
082: --waitingWriters;
083: claimWriteLock();
084: }
085:
086: public synchronized void unlockWrite() {
087: Debug.assertTrue(activeWriters == 1);
088: Debug.assertTrue(lockCount > 0);
089: Debug.assertTrue(Thread.currentThread() == writerThread);
090: if (--lockCount == 0) {
091: --activeWriters;
092: writerThread = null;
093: notifyAll();
094: }
095: }
096:
097: public synchronized boolean isWriteLocked() {
098: Debug.assertTrue(activeWriters == 0 || activeWriters == 1);
099: return activeWriters == 1;
100: }
101:
102: private final boolean allowRead() {
103: return waitingWriters == 0 && activeWriters == 0;
104: }
105:
106: private final boolean allowWrite() {
107: return activeReaders == 0 && activeWriters == 0;
108: }
109:
110: private void claimWriteLock() {
111: ++activeWriters;
112: Debug.assertTrue(writerThread == null);
113: writerThread = Thread.currentThread();
114: Debug.assertTrue(lockCount == 0);
115: lockCount = 1;
116: }
117: }
|