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 > 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 }