PageRenderTime 25ms CodeModel.GetById 14ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/util/ReadWriteLock.java

#
Java | 205 lines | 108 code | 19 blank | 78 comment | 28 complexity | f21203a929b58f223e816c309c686347 MD5 | raw file
  1/*
  2 * ReadWriteLock.java
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001 Peter Graves
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or (at your option) any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.util;
 24
 25import java.util.Vector;
 26
 27/**
 28 * Implements consumer/producer locking scemantics.
 29 * @author Peter Graves
 30 * @version $Id: ReadWriteLock.java 4970 2004-02-14 19:02:49Z spestov $
 31 * The lock tries to be re-entrant when called from the same thread in some
 32 * cases.
 33 * 
 34 * The following is ok:
 35 * read lock
 36 * read lock
 37 * read unlock
 38 * read unlock
 39 * 
 40 * write lock
 41 * read lock
 42 * read unlock
 43 * write unlock
 44 * 
 45 * The following is not ok:
 46 * 
 47 * read lock
 48 * write lock
 49 * write unlock
 50 * read unlock
 51 * 
 52 * write lock
 53 * write lock
 54 * write unlock
 55 * write unlock
 56 */
 57public class ReadWriteLock
 58{
 59	//{{{ readLock() method
 60	public synchronized void readLock()
 61	{
 62		// this seems to make nested readLock() calls work okay.
 63		// but I have no idea if it actually fixes things or not.
 64		if (activeReaders != 0 || allowRead())
 65		{
 66			++activeReaders;
 67			//readers.addElement(Thread.currentThread());
 68			return;
 69		}
 70		++waitingReaders;
 71		while (!allowRead())
 72		{
 73			try
 74			{
 75				wait();
 76			}
 77			catch (InterruptedException e)
 78			{
 79				--waitingReaders; // Roll back state.
 80				Log.log(Log.ERROR,this,e);
 81				return;
 82			}
 83		}
 84		--waitingReaders;
 85		++activeReaders;
 86		readers.addElement(Thread.currentThread());
 87	} //}}}
 88
 89	//{{{ readUnlock() method
 90	public synchronized void readUnlock()
 91	{
 92		if(activeReaders == 0)
 93			throw new InternalError("Unbalanced readLock()/readUnlock() calls");
 94
 95		--activeReaders;
 96		//readers.removeElement(Thread.currentThread());
 97		notifyAll();
 98	} //}}}
 99
100	//{{{ writeLock() method
101	public synchronized void writeLock()
102	{
103		if (writerThread != null)
104		{
105			// Write in progress.
106			if (Thread.currentThread() == writerThread)
107			{
108				// Same thread.
109				++lockCount;
110				return;
111			}
112		}
113		if (allowWrite())
114		{
115			claimWriteLock();
116			return;
117		}
118
119		++waitingWriters;
120		while (!allowWrite())
121		{
122			try
123			{
124				wait();
125			}
126			catch (InterruptedException e)
127			{
128				--waitingWriters;
129				Log.log(Log.ERROR,this,e);
130				return;
131			}
132		}
133		--waitingWriters;
134		claimWriteLock();
135	} //}}}
136
137	//{{{ writeUnlock() method
138	public synchronized void writeUnlock()
139	{
140		if(activeWriters != 1 || lockCount <= 0)
141			throw new InternalError("Unbalanced writeLock()/writeUnlock() calls");
142
143		if(Thread.currentThread() != writerThread)
144			throw new InternalError("writeUnlock() from wrong thread");
145
146		if (--lockCount == 0)
147		{
148			--activeWriters;
149			writerThread = null;
150			notifyAll();
151		}
152	} //}}}
153
154	//{{{ isWriteLocked() method
155	public synchronized boolean isWriteLocked()
156	{
157		//Debug.assert(activeWriters == 0 || activeWriters == 1);
158		return activeWriters == 1;
159	} //}}}
160
161	//{{{ Private members
162
163	//{{{ Instance variables
164	private int activeReaders;
165	private int activeWriters;
166	private int waitingReaders;
167	private int waitingWriters;
168	private Vector readers = new Vector();
169
170	private Thread writerThread;
171	private int lockCount;
172	//}}}
173
174	//{{{ allowRead() method
175	private final boolean allowRead()
176	{
177		return (Thread.currentThread() == writerThread)
178			|| (waitingWriters == 0 && activeWriters == 0);
179	} //}}}
180
181	//{{{ allowWrite() method
182	private final boolean allowWrite()
183	{
184		/*Thread current = Thread.currentThread();
185		for(int i = 0; i < readers.size(); i++)
186		{
187			if(readers.elementAt(i) == current)
188				throw new InternalError("Cannot nest writeLock() inside readLock()");
189		}*/
190
191		return activeReaders == 0 && activeWriters == 0;
192	} //}}}
193
194	//{{{ claimWriteLock() method
195	private void claimWriteLock()
196	{
197		++activeWriters;
198		//Debug.assert(writerThread == null);
199		writerThread = Thread.currentThread();
200		//Debug.assert(lockCount == 0);
201		lockCount = 1;
202	} //}}}
203
204	//}}}
205}