KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > util > ReadWriteLock


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
23 package org.gjt.sp.util;
24
25 import java.util.Vector JavaDoc;
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  */

57 public 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 JavaDoc 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 JavaDoc("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 JavaDoc 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 JavaDoc("Unbalanced writeLock()/writeUnlock() calls");
142
143         if(Thread.currentThread() != writerThread)
144             throw new InternalError JavaDoc("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 JavaDoc readers = new Vector JavaDoc();
169
170     private Thread JavaDoc 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
}
206
Popular Tags