Removed DOCUMENT ME comments that were generated and applied source code
[utils] / support / general / src / main / java / org / wamblee / concurrency / ReadWriteLock.java
1 /*
2  * Copyright 2005 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.wamblee.concurrency;
17
18 import java.util.HashSet;
19
20 /**
21  * Read-write lock for allowing multiple concurrent readers or at most one
22  * writer. This implementation does not aim for high performance but for
23  * robustness and simplicity. Users of this class should not synchronize on
24  * objects of this class.
25  */
26 public class ReadWriteLock {
27     /**
28      * Sets containing the references to the threads that are currently reading.
29      * This administration is useful to check that the lock has already been
30      * acquired before it is release. This check adds robustness to the
31      * application.
32      */
33     private HashSet<Thread> readers;
34
35     /**
36      * The thread that has acquired the lock for writing or null if no such
37      * thread exists currently.
38      */
39     private Thread writer;
40
41     /**
42      * Constructs read-write lock.
43      */
44     public ReadWriteLock() {
45         readers = new HashSet<Thread>();
46         writer = null;
47     }
48
49     /**
50      * Acquires the lock for reading. This call will block until the lock can be
51      * acquired.
52      * 
53      * @throws IllegalStateException
54      *             Thrown if the read or write lock is already acquired.
55      */
56     public synchronized void acquireRead() {
57         if (readers.contains(Thread.currentThread())) {
58             throw new IllegalStateException(
59                 "Read lock already acquired by current thread: " +
60                     Thread.currentThread());
61         }
62
63         if (writer == Thread.currentThread()) {
64             throw new IllegalStateException(
65                 "Trying to acquire the read lock while already holding a write lock: " +
66                     Thread.currentThread());
67         }
68
69         while (writer != null) {
70             try {
71                 wait();
72             } catch (InterruptedException e) {
73                 notifyAll();
74             }
75         }
76
77         readers.add(Thread.currentThread());
78     }
79
80     /**
81      * Releases the lock for reading. Note: This implementation assumes that the
82      * lock has already been acquired for reading previously.
83      * 
84      * @throws IllegalStateException
85      *             Thrown when the lock was not acquired by this thread.
86      */
87     public synchronized void releaseRead() {
88         if (!readers.remove(Thread.currentThread())) {
89             throw new IllegalStateException(
90                 "Cannot release read lock because current thread has not acquired it.");
91         }
92
93         if (readers.size() == 0) {
94             notifyAll();
95         }
96     }
97
98     /**
99      * Acquires the lock for writing. This call will block until the lock has
100      * been acquired.
101      * 
102      * @throws IllegalStateException
103      *             Thrown if the read or write lock is already acquired.
104      */
105     public synchronized void acquireWrite() {
106         if (writer == Thread.currentThread()) {
107             throw new IllegalStateException(
108                 "Trying to acquire a write lock while already holding the write lock: " +
109                     Thread.currentThread());
110         }
111
112         if (readers.contains(Thread.currentThread())) {
113             throw new IllegalStateException(
114                 "Trying to acquire a write lock while already holding the read lock: " +
115                     Thread.currentThread());
116         }
117
118         // wait until there are no more writers and no more
119         // readers
120         while ((writer != null) || (readers.size() > 0)) {
121             try {
122                 wait();
123             } catch (InterruptedException e) {
124                 notifyAll();
125             }
126         }
127
128         writer = Thread.currentThread();
129
130         // notification not necessary since all writers and
131         // readers are now blocked by this thread.
132     }
133
134     /**
135      * Releases the lock for writing.
136      * 
137      * @throws IllegalStateException
138      *             Thrown when the lock was not acquired.
139      */
140     public synchronized void releaseWrite() {
141         if (writer != Thread.currentThread()) {
142             throw new IllegalStateException(
143                 "Cannot release write lock because it was not acquired. ");
144         }
145
146         writer = null;
147         notifyAll();
148     }
149 }