001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package java.util.concurrent.locks;
006:
007: import com.tc.exception.TCNotSupportedMethodException;
008: import com.tc.exception.TCObjectNotSharableException;
009: import com.tc.object.TCObject;
010: import com.tc.object.bytecode.Manageable;
011: import com.tc.object.bytecode.ManagerUtil;
012: import com.tc.object.lockmanager.api.LockLevel;
013: import com.tc.util.concurrent.locks.TCLock;
014: import com.tcclient.util.concurrent.locks.ConditionObject;
015:
016: import java.util.Collection;
017: import java.util.concurrent.TimeUnit;
018:
019: public class ReentrantReadWriteLockTC extends ReentrantReadWriteLock {
020: private ReentrantReadWriteLock.ReadLock readerLock;
021: private ReentrantReadWriteLock.WriteLock writerLock;
022: private Sync sync;
023:
024: private static class DsoLock {
025: private final Object lock;
026: private final int lockLevel;
027:
028: public DsoLock(Object lock, int lockLevel) {
029: this .lock = lock;
030: this .lockLevel = lockLevel;
031: }
032:
033: public void lock() {
034: if (ManagerUtil.isManaged(lock)) {
035: ManagerUtil.monitorEnter(lock, lockLevel);
036: }
037: }
038:
039: public boolean tryLock() {
040: if (ManagerUtil.isManaged(lock)) {
041: return ManagerUtil.tryMonitorEnter(lock, 0, lockLevel);
042: } else {
043: return true;
044: }
045: }
046:
047: public boolean tryLock(long timeout, TimeUnit unit) {
048: if (ManagerUtil.isManaged(lock)) {
049: long timeoutInNanos = TimeUnit.NANOSECONDS.convert(
050: timeout, unit);
051: return ManagerUtil.tryMonitorEnter(lock,
052: timeoutInNanos, lockLevel);
053: } else {
054: return true;
055: }
056: }
057:
058: public void unlock() {
059: if (ManagerUtil.isManaged(lock)) {
060: ManagerUtil.monitorExit(lock);
061: }
062: }
063:
064: public Object getDsoLock() {
065: return lock;
066: }
067:
068: public String getLockState(int lockLevel) {
069: return (ManagerUtil.isLocked(lock, lockLevel) ? (ManagerUtil
070: .isHeldByCurrentThread(lock, lockLevel) ? "[Locally locked]"
071: : "[Remotelly locked]")
072: : "[Unlocked]");
073: }
074:
075: }
076:
077: public static class ReadLock extends
078: ReentrantReadWriteLock.ReadLock implements Manageable {
079: private volatile transient TCObject $__tc_MANAGED;
080: private transient DsoLock dsoLock;
081: private Sync sync;
082:
083: protected ReadLock(ReentrantReadWriteLockTC lock, Sync sync) {
084: super (lock);
085: dsoLock = new DsoLock(sync, LockLevel.READ);
086: }
087:
088: public void lock() {
089: dsoLock.lock();
090: super .lock();
091: }
092:
093: public void lockInterruptibly() throws InterruptedException {
094: if (Thread.interrupted()) {
095: throw new InterruptedException();
096: }
097:
098: try {
099: dsoLock.lock();
100: super .lockInterruptibly();
101: } finally {
102: if (Thread.interrupted()) {
103: unlock();
104: throw new InterruptedException();
105: }
106: }
107: }
108:
109: public boolean tryLock() {
110: boolean isLocked = dsoLock.tryLock();
111: if (isLocked
112: || !ManagerUtil.isManaged(dsoLock.getDsoLock())) {
113: isLocked = super .tryLock();
114: }
115: return isLocked;
116: }
117:
118: public boolean tryLock(long timeout, TimeUnit unit)
119: throws InterruptedException {
120: boolean isLocked = dsoLock.tryLock(timeout, unit);
121: if (isLocked
122: || !ManagerUtil.isManaged(dsoLock.getDsoLock())) {
123: isLocked = super .tryLock(timeout, unit);
124: }
125: return isLocked;
126: }
127:
128: public void unlock() {
129: super .unlock();
130: dsoLock.unlock();
131: }
132:
133: public String toString() {
134: if (ManagerUtil.isManaged(this )) {
135: String objectString = getClass().getName() + "@"
136: + Integer.toHexString(hashCode());
137: return (new StringBuilder()).append(objectString)
138: .append(dsoLock.getLockState(LockLevel.READ))
139: .toString();
140: } else {
141: return super .toString();
142: }
143: }
144:
145: private void readObject(java.io.ObjectInputStream s)
146: throws java.io.IOException, ClassNotFoundException {
147: s.defaultReadObject();
148: this .dsoLock = new DsoLock(sync, LockLevel.READ);
149: }
150:
151: public void __tc_managed(TCObject tcObject) {
152: $__tc_MANAGED = tcObject;
153: }
154:
155: public TCObject __tc_managed() {
156: return $__tc_MANAGED;
157: }
158:
159: public boolean __tc_isManaged() {
160: return $__tc_MANAGED != null;
161: }
162: }
163:
164: public static class WriteLock extends
165: ReentrantReadWriteLock.WriteLock implements TCLock,
166: Manageable {
167: private volatile transient TCObject $__tc_MANAGED;
168: private transient DsoLock dsoLock;
169: private Sync sync;
170:
171: protected WriteLock(ReentrantReadWriteLockTC lock, Sync sync) {
172: super (lock);
173: this .dsoLock = new DsoLock(sync, LockLevel.WRITE);
174: }
175:
176: public void lock() {
177: dsoLock.lock();
178: super .lock();
179: }
180:
181: public void lockInterruptibly() throws InterruptedException {
182: if (Thread.interrupted()) {
183: throw new InterruptedException();
184: }
185:
186: try {
187: dsoLock.lock();
188: super .lockInterruptibly();
189: } finally {
190: if (Thread.interrupted()) {
191: unlock();
192: throw new InterruptedException();
193: }
194: }
195: }
196:
197: public boolean tryLock() {
198: boolean isLocked = dsoLock.tryLock();
199: if (isLocked
200: || !ManagerUtil.isManaged(dsoLock.getDsoLock())) {
201: isLocked = super .tryLock();
202: }
203: return isLocked;
204: }
205:
206: public boolean tryLock(long timeout, TimeUnit unit)
207: throws InterruptedException {
208: boolean isLocked = dsoLock.tryLock(timeout, unit);
209: if (isLocked
210: || !ManagerUtil.isManaged(dsoLock.getDsoLock())) {
211: isLocked = super .tryLock(timeout, unit);
212: }
213: return isLocked;
214: }
215:
216: public void unlock() {
217: super .unlock();
218: dsoLock.unlock();
219: }
220:
221: public Condition newCondition() {
222: return new ConditionObject(this );
223: }
224:
225: public Object getTCLockingObject() {
226: return dsoLock.getDsoLock();
227: }
228:
229: public boolean isHeldByCurrentThread() {
230: return sync.isHeldExclusively();
231: }
232:
233: public int localHeldCount() {
234: return sync.getWriteHoldCount();
235: }
236:
237: private void readObject(java.io.ObjectInputStream s)
238: throws java.io.IOException, ClassNotFoundException {
239: s.defaultReadObject();
240: this .dsoLock = new DsoLock(sync, LockLevel.WRITE);
241: }
242:
243: public String toString() {
244: if (ManagerUtil.isManaged(this )) {
245: String objectString = getClass().getName() + "@"
246: + Integer.toHexString(hashCode());
247: return (new StringBuilder()).append(objectString)
248: .append(dsoLock.getLockState(LockLevel.WRITE))
249: .toString();
250: } else {
251: return super .toString();
252: }
253: }
254:
255: public void __tc_managed(TCObject tcObject) {
256: $__tc_MANAGED = tcObject;
257: }
258:
259: public TCObject __tc_managed() {
260: return $__tc_MANAGED;
261: }
262:
263: public boolean __tc_isManaged() {
264: return $__tc_MANAGED != null;
265: }
266: }
267:
268: protected Thread getOwner() {
269: if (ManagerUtil.isManaged(this )) {
270: throw new TCNotSupportedMethodException();
271: } else {
272: return super .getOwner();
273: }
274: }
275:
276: protected Collection<Thread> getQueuedReaderThreads() {
277: if (ManagerUtil.isManaged(this )) {
278: throw new TCNotSupportedMethodException();
279: } else {
280: return super .getQueuedReaderThreads();
281: }
282: }
283:
284: protected Collection<Thread> getQueuedThreads() {
285: if (ManagerUtil.isManaged(this )) {
286: throw new TCNotSupportedMethodException();
287: } else {
288: return super .getQueuedThreads();
289: }
290: }
291:
292: protected Collection<Thread> getQueuedWriterThreads() {
293: if (ManagerUtil.isManaged(this )) {
294: throw new TCNotSupportedMethodException();
295: } else {
296: return super .getQueuedWriterThreads();
297: }
298: }
299:
300: // TODO: need to review
301: public int getReadLockCount() {
302: if (ManagerUtil.isManaged(this )) {
303: return ManagerUtil.localHeldCount(sync, LockLevel.READ);
304: } else {
305: return super .getReadLockCount();
306: }
307: }
308:
309: protected Collection<Thread> getWaitingThreads(Condition condition) {
310: if (ManagerUtil.isManaged(this )) {
311: throw new TCNotSupportedMethodException();
312: } else {
313: if (condition == null)
314: throw new NullPointerException();
315: if (!(condition instanceof ConditionObject))
316: throw new IllegalArgumentException("not owner");
317: return ((ConditionObject) condition)
318: .getWaitingThreads(writeLock());
319: }
320: }
321:
322: public int getWaitQueueLength(Condition condition) {
323: if (condition == null)
324: throw new NullPointerException();
325: if (!(condition instanceof ConditionObject))
326: throw new IllegalArgumentException("not owner");
327: return ((ConditionObject) condition)
328: .getWaitQueueLength(writeLock());
329: }
330:
331: public int getWriteHoldCount() {
332: return super .getWriteHoldCount();
333: }
334:
335: public boolean hasWaiters(Condition condition) {
336: if (condition == null)
337: throw new NullPointerException();
338: if (!(condition instanceof ConditionObject))
339: throw new IllegalArgumentException("not owner");
340: return ((ConditionObject) condition)
341: .getWaitQueueLength(writeLock()) > 0;
342: }
343:
344: public boolean isWriteLocked() {
345: if (ManagerUtil.isManaged(this )) {
346: return ManagerUtil.isLocked(sync, LockLevel.WRITE);
347: } else {
348: return super .isWriteLocked();
349: }
350: }
351:
352: private void readObject(java.io.ObjectInputStream s)
353: throws java.io.IOException, ClassNotFoundException {
354: s.defaultReadObject();
355: readerLock = new ReadLock(this , sync);
356: writerLock = new WriteLock(this , sync);
357: }
358:
359: public void validateInUnLockState() {
360: boolean isLocked = super .getReadLockCount() != 0
361: || super .isWriteLocked();
362: if (isLocked) {
363: throw new TCObjectNotSharableException(
364: "You are attempting to share a ReentrantReadWriteLock when it is in a locked state. Lock cannot be shared while locked.");
365: }
366: }
367:
368: public Sync getSync() {
369: return sync;
370: }
371:
372: // TODO: need to review
373: public String toString() {
374: if (ManagerUtil.isManaged(this )) {
375: String objectString = getClass().getName() + "@"
376: + Integer.toHexString(hashCode());
377: return objectString + "[Write locks = " + writeLock()
378: + ", Read locks = " + readLock() + "]";
379: } else {
380: return super.toString();
381: }
382: }
383: }
|