View Javadoc
1   //******************************************************************************
2   //
3   // File:    Lock.java
4   // Package: edu.rit.pj
5   // Unit:    Class edu.rit.pj.Lock
6   //
7   // This Java source file is copyright (C) 2007 by Alan Kaminsky. All rights
8   // reserved. For further information, contact the author, Alan Kaminsky, at
9   // ark@cs.rit.edu.
10  //
11  // This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
12  // software; you can redistribute it and/or modify it under the terms of the GNU
13  // General Public License as published by the Free Software Foundation; either
14  // version 3 of the License, or (at your option) any later version.
15  //
16  // PJ is distributed in the hope that it will be useful, but WITHOUT ANY
17  // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18  // A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19  //
20  // Linking this library statically or dynamically with other modules is making a
21  // combined work based on this library. Thus, the terms and conditions of the GNU
22  // General Public License cover the whole combination.
23  //
24  // As a special exception, the copyright holders of this library give you
25  // permission to link this library with independent modules to produce an
26  // executable, regardless of the license terms of these independent modules, and
27  // to copy and distribute the resulting executable under terms of your choice,
28  // provided that you also meet, for each linked independent module, the terms
29  // and conditions of the license of that module. An independent module is a module
30  // which is not derived from or based on this library. If you modify this library,
31  // you may extend this exception to your version of the library, but you are not
32  // obligated to do so. If you do not wish to do so, delete this exception
33  // statement from your version.
34  //
35  // A copy of the GNU General Public License is provided in the file gpl.txt. You
36  // may also obtain a copy of the GNU General Public License on the World Wide
37  // Web at http://www.gnu.org/licenses/gpl.html.
38  //
39  //******************************************************************************
40  package edu.rit.pj;
41  
42  import java.io.Serial;
43  import java.util.concurrent.locks.AbstractQueuedSynchronizer;
44  
45  /**
46   * Class Lock provides an object used for synchronizing parallel team threads in
47   * a critical region. You don't call methods on a Lock object directly, rather
48   * you pass a Lock object to the <code>critical()</code> or
49   * <code>criticalNonexclusive()</code> methods of class {@linkplain ParallelRegion}.
50   *
51   * @author Alan Kaminsky
52   * @version 05-Jun-2007
53   */
54  public class Lock {
55  
56  // Hidden helper classes.
57      /**
58       * Class Lock.Synchronizer does the actual work. The synchronizer state, a
59       * single <code>int</code>, is interpreted as follows: state = 0 means unlocked;
60       * state &gt; 0 means locked nonexclusively, with the state giving the
61       * number of threads that have acquired the lock; state = -1 means locked
62       * exclusively, with one thread having acquired the lock.
63       *
64       * @author Alan Kaminsky
65       * @version 05-Jun-2007
66       */
67      private static class Synchronizer
68              extends AbstractQueuedSynchronizer {
69  
70          @Serial
71          private static final long serialVersionUID = 1L;
72  
73          /**
74           * Construct a new lock synchronizer.
75           */
76          public Synchronizer() {
77              super();
78          }
79  
80          /**
81           * Acquire the lock exclusively.
82           *
83           * @param arg Ignored.
84           *
85           * @return True if acquired, false otherwise.
86           */
87          protected boolean tryAcquire(int arg) {
88              for (;;) {
89                  int oldstate = getState();
90                  if (oldstate != 0) {
91                      return false;
92                  }
93                  if (compareAndSetState(0, -1)) {
94                      return true;
95                  }
96              }
97          }
98  
99          /**
100          * Release the lock exclusively.
101          *
102          * @param arg Ignored.
103          *
104          * @return True if released, false otherwise.
105          */
106         protected boolean tryRelease(int arg) {
107             setState(0);
108             return true;
109         }
110 
111         /**
112          * Acquire the lock nonexclusively.
113          *
114          * @param arg Ignored.
115          *
116          * @return A positive value if successfully acquired nonexclusively,
117          * zero if successfully acquired exclusively, a negative value if not
118          * acquired.
119          */
120         protected int tryAcquireShared(int arg) {
121             for (;;) {
122                 int oldstate = getState();
123                 if (oldstate < 0) {
124                     return -1;
125                 }
126                 int newstate = oldstate + 1;
127                 if (compareAndSetState(oldstate, newstate)) {
128                     return 1;
129                 }
130             }
131         }
132 
133         /**
134          * Release the lock nonexclusively.
135          *
136          * @param arg Ignored.
137          *
138          * @return True if released, false otherwise.
139          */
140         protected boolean tryReleaseShared(int arg) {
141             for (;;) {
142                 int oldstate = getState();
143                 int newstate = oldstate - 1;
144                 if (compareAndSetState(oldstate, newstate)) {
145                     return true;
146                 }
147             }
148         }
149     }
150 
151 // Hidden data members.
152     private Synchronizer mySynchronizer = new Synchronizer();
153 
154 // Exported constructors.
155     /**
156      * Construct a new lock.
157      */
158     public Lock() {
159     }
160 
161 // Hidden operations.
162     /**
163      * Lock an exclusive lock.
164      */
165     void lockExclusive() {
166         mySynchronizer.acquire(0);
167     }
168 
169     /**
170      * Unlock an exclusive lock.
171      */
172     void unlockExclusive() {
173         mySynchronizer.release(0);
174     }
175 
176     /**
177      * Lock a nonexclusive lock.
178      */
179     void lockNonexclusive() {
180         mySynchronizer.acquireShared(0);
181     }
182 
183     /**
184      * Unlock a nonexclusive lock.
185      */
186     void unlockNonexclusive() {
187         mySynchronizer.releaseShared(0);
188     }
189 
190 }