ReaderWriterLock.java 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* ========================================================================
  2. * JCommon : a free general purpose class library for the Java(tm) platform
  3. * ========================================================================
  4. *
  5. * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
  6. *
  7. * Project Info: http://www.jfree.org/jcommon/index.html
  8. *
  9. * This library is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU Lesser General Public License as published by
  11. * the Free Software Foundation; either version 2.1 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  17. * License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
  22. * USA.
  23. *
  24. * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
  25. * in the United States and other countries.]
  26. *
  27. * ---------------------
  28. * ReaderWriterLock.java
  29. * ---------------------
  30. *
  31. * $Id: ReaderWriterLock.java,v 1.3 2005/10/18 13:18:34 mungady Exp $
  32. *
  33. * Changes
  34. * -------
  35. * 29-Jan-2003 : Added standard header (DG);
  36. *
  37. */
  38. package org.jfree.threads;
  39. import java.util.ArrayList;
  40. import java.util.Iterator;
  41. /**
  42. * A reader-writer lock from "Java Threads" by Scott Oak and Henry Wong.
  43. *
  44. * @author Scott Oak and Henry Wong
  45. */
  46. public class ReaderWriterLock {
  47. /**
  48. * A node for the waiting list.
  49. *
  50. * @author Scott Oak and Henry Wong
  51. */
  52. private static class ReaderWriterNode {
  53. /** A reader. */
  54. protected static final int READER = 0;
  55. /** A writer. */
  56. protected static final int WRITER = 1;
  57. /** The thread. */
  58. protected Thread t;
  59. /** The state. */
  60. protected int state;
  61. /** The number of acquires.*/
  62. protected int nAcquires;
  63. /**
  64. * Creates a new node.
  65. *
  66. * @param t the thread.
  67. * @param state the state.
  68. */
  69. private ReaderWriterNode(final Thread t, final int state) {
  70. this.t = t;
  71. this.state = state;
  72. this.nAcquires = 0;
  73. }
  74. }
  75. /** The waiting threads. */
  76. private ArrayList waiters;
  77. /**
  78. * Default constructor.
  79. */
  80. public ReaderWriterLock() {
  81. this.waiters = new ArrayList();
  82. }
  83. /**
  84. * Grab the read lock.
  85. */
  86. public synchronized void lockRead() {
  87. final ReaderWriterNode node;
  88. final Thread me = Thread.currentThread();
  89. final int index = getIndex(me);
  90. if (index == -1) {
  91. node = new ReaderWriterNode(me, ReaderWriterNode.READER);
  92. this.waiters.add(node);
  93. }
  94. else {
  95. node = (ReaderWriterNode) this.waiters.get(index);
  96. }
  97. while (getIndex(me) > firstWriter()) {
  98. try {
  99. wait();
  100. }
  101. catch (Exception e) {
  102. System.err.println("ReaderWriterLock.lockRead(): exception.");
  103. System.err.print(e.getMessage());
  104. }
  105. }
  106. node.nAcquires++;
  107. }
  108. /**
  109. * Grab the write lock.
  110. */
  111. public synchronized void lockWrite() {
  112. final ReaderWriterNode node;
  113. final Thread me = Thread.currentThread();
  114. final int index = getIndex(me);
  115. if (index == -1) {
  116. node = new ReaderWriterNode(me, ReaderWriterNode.WRITER);
  117. this.waiters.add(node);
  118. }
  119. else {
  120. node = (ReaderWriterNode) this.waiters.get(index);
  121. if (node.state == ReaderWriterNode.READER) {
  122. throw new IllegalArgumentException("Upgrade lock");
  123. }
  124. node.state = ReaderWriterNode.WRITER;
  125. }
  126. while (getIndex(me) != 0) {
  127. try {
  128. wait();
  129. }
  130. catch (Exception e) {
  131. System.err.println("ReaderWriterLock.lockWrite(): exception.");
  132. System.err.print(e.getMessage());
  133. }
  134. }
  135. node.nAcquires++;
  136. }
  137. /**
  138. * Unlock.
  139. */
  140. public synchronized void unlock() {
  141. final ReaderWriterNode node;
  142. final Thread me = Thread.currentThread();
  143. final int index = getIndex(me);
  144. if (index > firstWriter()) {
  145. throw new IllegalArgumentException("Lock not held");
  146. }
  147. node = (ReaderWriterNode) this.waiters.get(index);
  148. node.nAcquires--;
  149. if (node.nAcquires == 0) {
  150. this.waiters.remove(index);
  151. }
  152. notifyAll();
  153. }
  154. /**
  155. * Returns the index of the first waiting writer.
  156. *
  157. * @return The index.
  158. */
  159. private int firstWriter() {
  160. final Iterator e = this.waiters.iterator();
  161. int index = 0;
  162. while (e.hasNext()) {
  163. final ReaderWriterNode node = (ReaderWriterNode) e.next();
  164. if (node.state == ReaderWriterNode.WRITER) {
  165. return index;
  166. }
  167. index += 1;
  168. }
  169. return Integer.MAX_VALUE;
  170. }
  171. /**
  172. * Returns the index of a thread.
  173. *
  174. * @param t the thread.
  175. *
  176. * @return The index.
  177. */
  178. private int getIndex(final Thread t) {
  179. final Iterator e = this.waiters.iterator();
  180. int index = 0;
  181. while (e.hasNext()) {
  182. final ReaderWriterNode node = (ReaderWriterNode) e.next();
  183. if (node.t == t) {
  184. return index;
  185. }
  186. index += 1;
  187. }
  188. return -1;
  189. }
  190. }