001: /**
002: * $RCSfile: $
003: * $Revision: $
004: * $Date: $
005: *
006: * Copyright (C) 2007 Jive Software. All rights reserved.
007: *
008: * This software is published under the terms of the GNU Public License (GPL),
009: * a copy of which is included in this distribution.
010: */package org.jivesoftware.util.lock;
011:
012: import org.jivesoftware.util.TaskEngine;
013:
014: import java.lang.ref.WeakReference;
015: import java.util.Map;
016: import java.util.TimerTask;
017: import java.util.concurrent.ConcurrentHashMap;
018: import java.util.concurrent.TimeUnit;
019: import java.util.concurrent.locks.Lock;
020: import java.util.concurrent.locks.ReentrantLock;
021: import java.util.concurrent.locks.Condition;
022:
023: /**
024: * LockFactory to be used when not running in cluster mode. The locks returned by this
025: * factory are only visibile within this JVM.
026: *
027: * @author Gaston Dombiak
028: */
029: public class LocalLockFactory implements LockFactory {
030:
031: private Map<Object, LockAndCount> locks = new ConcurrentHashMap<Object, LockAndCount>();
032:
033: public Lock getLock(Object key) {
034: Object lockKey = key;
035: if (key instanceof String) {
036: lockKey = ((String) key).intern();
037: }
038:
039: return new LocalLock(lockKey);
040: }
041:
042: private void acquireLock(Object key) {
043: ReentrantLock lock = lookupLockForAcquire(key);
044: lock.lock();
045: }
046:
047: private void releaseLock(Object key) {
048: ReentrantLock lock = lookupLockForRelease(key);
049: lock.unlock();
050: }
051:
052: private ReentrantLock lookupLockForAcquire(Object key) {
053: synchronized (key) {
054: LockAndCount lac = locks.get(key);
055: if (lac == null) {
056: lac = new LockAndCount(new ReentrantLock());
057: lac.count = 1;
058: locks.put(key, lac);
059: } else {
060: lac.count++;
061: }
062:
063: return lac.lock;
064: }
065: }
066:
067: private ReentrantLock lookupLockForRelease(Object key) {
068: synchronized (key) {
069: LockAndCount lac = locks.get(key);
070: if (lac == null) {
071: throw new IllegalStateException(
072: "No lock found for object " + key);
073: }
074:
075: if (lac.count <= 1) {
076: locks.remove(key);
077: } else {
078: lac.count--;
079: }
080:
081: return lac.lock;
082: }
083: }
084:
085: private class LocalLock implements Lock {
086: private final Object key;
087:
088: LocalLock(Object key) {
089: this .key = key;
090: }
091:
092: public void lock() {
093: acquireLock(key);
094: }
095:
096: public void unlock() {
097: releaseLock(key);
098: }
099:
100: public void lockInterruptibly() {
101: throw new UnsupportedOperationException();
102: }
103:
104: public Condition newCondition() {
105: throw new UnsupportedOperationException();
106: }
107:
108: public boolean tryLock() {
109: throw new UnsupportedOperationException();
110: }
111:
112: public boolean tryLock(long time, TimeUnit unit) {
113: throw new UnsupportedOperationException();
114: }
115:
116: }
117:
118: private static class LockAndCount {
119: final ReentrantLock lock;
120: int count;
121:
122: LockAndCount(ReentrantLock lock) {
123: this.lock = lock;
124: }
125: }
126: }
|