View Javadoc

1   /*
2    * ReadWriteLock.java
3    *
4    * Created on January 25, 2005, 10:39 AM
5    */
6   
7   package gov.bnl.gums;
8   
9   import org.apache.commons.logging.Log;
10  import org.apache.commons.logging.LogFactory;
11  
12  /*** Implements a lock to prevent access to GUMS data when updating. This is
13   * essentially the same as ReadWriteLock in JDK 1.5 (which I discovered after
14   * implementing this), which can't be used as we need JDK 1.4 compatibility.
15   * In the future it can be eliminated.
16   * <p>
17   * The write lock is exclusive, while the read locks allows for concurrent reads.
18   * Once the write lock is requested, no more reads are accepted. The write lock
19   * is guaranteed only when all read locks are released.
20   *
21   * @author Gabriele Carcassi
22   */
23  public class ReadWriteLock {
24      private Log log = LogFactory.getLog(ReadWriteLock.class);
25      
26      private int[] lock = new int[2];
27      private String name;
28      
29      public ReadWriteLock(String name) {
30          this.name = name;
31      }
32      
33      /*** Checks whether anybody has a read lock.
34       */
35      public synchronized boolean isReadLocked() {
36          return lock[1] != 0;
37      }
38      
39      /*** Checks whether anybody is reading data.
40       */
41      public synchronized boolean isWriteLocked() {
42          return lock[0] != 0;
43      }
44      
45      public synchronized void obtainWriteLock() {
46          log.trace("Trying to write on " + name + ": " + lock[0] + ", " + lock[1]);
47          
48          // Book a write
49          while (lock[1] != 0) {
50              try {
51                  log.trace("Waiting write on " + name + ": " + lock[0] + ", " + lock[1]);
52                  wait();
53              } catch (InterruptedException e) {
54                  log.error("Wait was interrupted: " + e.getMessage(), e);
55              }
56          }
57          lock[1] = 1;
58          log.trace("Locked write on " + name + ": " + lock[0] + ", " + lock[1]);
59          notifyAll();
60          
61          // Wait all the readers are done
62          while (lock[0] != 0) {
63              try {
64                  wait();
65              } catch (InterruptedException e) {
66                  log.error("Wait was interrupted: " + e.getMessage(), e);
67              }
68          }
69      }
70      
71      public synchronized void releaseWriteLock() {
72          log.trace("Unlocking write on " + name + ": " + lock[0] + ", " + lock[1]);
73          lock[1]=0;
74          log.trace("Unocked write on " + name + ": " + lock[0] + ", " + lock[1]);
75          notifyAll();
76      }
77      
78      public synchronized void obtainReadLock() {
79          log.trace("Trying to read on " + name + ": " + lock[0] + ", " + lock[1]);
80          // Wait that writes are finished
81          while (lock[1] != 0) {
82              try {
83                  log.trace("Waiting read on " + name + ": " + lock[0] + ", " + lock[1]);
84                  wait();
85              } catch (InterruptedException e) {
86                  log.error("Wait was interrupted: " + e.getMessage(), e);
87              }
88          }
89          
90          // Increase read counter
91          lock[0]++;
92          log.trace("Locked read on " + name + ": " + lock[0] + ", " + lock[1]);
93          notifyAll();
94      }
95      
96      public synchronized void releaseReadLock() {
97          log.trace("Unlocking read on " + name + ": " + lock[0] + ", " + lock[1]);
98          lock[0]--;
99          log.trace("Unocked read on " + name + ": " + lock[0] + ", " + lock[1]);
100         notifyAll();
101     }
102     
103 }