View Javadoc

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