(no commit message)
[utils] / support / general / src / main / java / org / wamblee / concurrency / ReadWriteLock.java
1 /*
2  * Copyright 2005-2010 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  * This class was originally developed for a Java developer certification. It is
27  * deprecated now and {@link java.util.concurrent.locks.ReadWriteLock} should be
28  * used instead.
29  */
30 @Deprecated
31 public class ReadWriteLock {
32     /**
33      * Sets containing the references to the threads that are currently reading.
34      * This administration is useful to check that the lock has already been
35      * acquired before it is release. This check adds robustness to the
36      * application.
37      */
38     private HashSet<Thread> readers;
39
40     /**
41      * The thread that has acquired the lock for writing or null if no such
42      * thread exists currently.
43      */
44     private Thread writer;
45
46     /**
47      * Constructs read-write lock.
48      */
49     public ReadWriteLock() {
50         readers = new HashSet<Thread>();
51         writer = null;
52     }
53
54     /**
55      * Acquires the lock for reading. This call will block until the lock can be
56      * acquired.
57      * 
58      * @throws IllegalStateException
59      *             Thrown if the read or write lock is already acquired.
60      */
61     public synchronized void acquireRead() {
62         if (readers.contains(Thread.currentThread())) {
63             throw new IllegalStateException(
64                 "Read lock already acquired by current thread: " +
65                     Thread.currentThread());
66         }
67
68         if (writer == Thread.currentThread()) {
69             throw new IllegalStateException(
70                 "Trying to acquire the read lock while already holding a write lock: " +
71                     Thread.currentThread());
72         }
73
74         while (writer != null) {
75             try {
76                 wait();
77             } catch (InterruptedException e) {
78                 notifyAll();
79             }
80         }
81
82         readers.add(Thread.currentThread());
83     }
84
85     /**
86      * Releases the lock for reading. Note: This implementation assumes that the
87      * lock has already been acquired for reading previously.
88      * 
89      * @throws IllegalStateException
90      *             Thrown when the lock was not acquired by this thread.
91      */
92     public synchronized void releaseRead() {
93         if (!readers.remove(Thread.currentThread())) {
94             throw new IllegalStateException(
95                 "Cannot release read lock because current thread has not acquired it.");
96         }
97
98         if (readers.size() == 0) {
99             notifyAll();
100         }
101     }
102
103     /**
104      * Acquires the lock for writing. This call will block until the lock has
105      * been acquired.
106      * 
107      * @throws IllegalStateException
108      *             Thrown if the read or write lock is already acquired.
109      */
110     public synchronized void acquireWrite() {
111         if (writer == Thread.currentThread()) {
112             throw new IllegalStateException(
113                 "Trying to acquire a write lock while already holding the write lock: " +
114                     Thread.currentThread());
115         }
116
117         if (readers.contains(Thread.currentThread())) {
118             throw new IllegalStateException(
119                 "Trying to acquire a write lock while already holding the read lock: " +
120                     Thread.currentThread());
121         }
122
123         // wait until there are no more writers and no more
124         // readers
125         while ((writer != null) || (readers.size() > 0)) {
126             try {
127                 wait();
128             } catch (InterruptedException e) {
129                 notifyAll();
130             }
131         }
132
133         writer = Thread.currentThread();
134
135         // notification not necessary since all writers and
136         // readers are now blocked by this thread.
137     }
138
139     /**
140      * Releases the lock for writing.
141      * 
142      * @throws IllegalStateException
143      *             Thrown when the lock was not acquired.
144      */
145     public synchronized void releaseWrite() {
146         if (writer != Thread.currentThread()) {
147             throw new IllegalStateException(
148                 "Cannot release write lock because it was not acquired. ");
149         }
150
151         writer = null;
152         notifyAll();
153     }
154 }