Author: manik.surtani(a)jboss.com
Date: 2008-07-30 11:43:05 -0400 (Wed, 30 Jul 2008)
New Revision: 6442
Added:
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/LockContainer.java
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLockContainer.java
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/ReentrantLockContainer.java
Modified:
core/trunk/src/main/java/org/jboss/cache/lock/MVCCLockManager.java
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockAssert.java
core/trunk/src/test/java/org/jboss/cache/lock/MVCCLockManagerRecordingTest.java
Log:
Exracted LockContainer to separate class for better reuse
Modified: core/trunk/src/main/java/org/jboss/cache/lock/MVCCLockManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/lock/MVCCLockManager.java 2008-07-30 15:42:20
UTC (rev 6441)
+++ core/trunk/src/main/java/org/jboss/cache/lock/MVCCLockManager.java 2008-07-30 15:43:05
UTC (rev 6442)
@@ -1,6 +1,5 @@
package org.jboss.cache.lock;
-import net.jcip.annotations.ThreadSafe;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheSPI;
@@ -14,10 +13,12 @@
import org.jboss.cache.invocation.InvocationContext;
import org.jboss.cache.invocation.InvocationContextContainer;
import static org.jboss.cache.lock.LockType.READ;
+import org.jboss.cache.util.concurrent.locks.LockContainer;
import org.jboss.cache.util.concurrent.locks.OwnableReentrantLock;
+import org.jboss.cache.util.concurrent.locks.OwnableReentrantLockContainer;
+import org.jboss.cache.util.concurrent.locks.ReentrantLockContainer;
import javax.transaction.TransactionManager;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -26,7 +27,6 @@
import java.util.Set;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
/**
* This lock manager acquires and releases locks based on the Fqn passed in and not on
the node itself. The main benefit
@@ -48,7 +48,7 @@
*/
public class MVCCLockManager extends FqnLockManager
{
- LockContainer lockContainer;
+ LockContainer<Fqn> lockContainer;
DataContainer dataContainer;
private Set<Fqn> internalFqns;
private CacheSPI<?, ?> cache;
@@ -69,7 +69,7 @@
@Start
public void startLockManager()
{
- lockContainer = transactionManager == null ? new ReentrantLockContainer() : new
OwnableReentrantLockContainer();
+ lockContainer = transactionManager == null ? new
ReentrantLockContainer<Fqn>(configuration.getConcurrencyLevel()) : new
OwnableReentrantLockContainer<Fqn>(configuration.getConcurrencyLevel(),
invocationContextContainer);
}
@Start
@@ -281,150 +281,4 @@
{
return lockContainer.toString();
}
-
- @ThreadSafe
- public abstract class LockContainer
- {
- private final int lockSegmentMask;
- private final int lockSegmentShift;
-
- /**
- * Creates a new LockContainer which uses a certain number of shared locks across
all elements that need to be locked.
- */
- LockContainer()
- {
- int tempLockSegShift = 0;
- int numLocks = 1;
- while (numLocks < configuration.getConcurrencyLevel())
- {
- ++tempLockSegShift;
- numLocks <<= 1;
- }
- lockSegmentShift = 32 - tempLockSegShift;
- lockSegmentMask = numLocks - 1;
-
- initLocks(numLocks);
- }
-
- final int hashToIndex(Fqn fqn)
- {
- return (hash(fqn) >>> lockSegmentShift) & lockSegmentMask;
- }
-
- /**
- * Returns a hash code for non-null Object x.
- * Uses the same hash code spreader as most other java.util hash tables, except
that this uses the string representation
- * of the object passed in.
- *
- * @param fqn the object serving as a key
- * @return the hash code
- */
- final int hash(Fqn fqn)
- {
- int h = fqn.hashCode();
- h += ~(h << 9);
- h ^= (h >>> 14);
- h += (h << 4);
- h ^= (h >>> 10);
- return h;
- }
-
- abstract void initLocks(int numLocks);
-
- abstract boolean ownsLock(Fqn fqn, Object owner);
-
- abstract boolean isLocked(Fqn fqn);
-
- abstract Lock getLock(Fqn fqn);
-
- public abstract int getNumLocksHeld();
- }
-
- public class ReentrantLockContainer extends LockContainer
- {
- ReentrantLock[] sharedLocks;
-
- void initLocks(int numLocks)
- {
- sharedLocks = new ReentrantLock[numLocks];
- for (int i = 0; i < numLocks; i++) sharedLocks[i] = new ReentrantLock();
- }
-
- ReentrantLock getLock(Fqn fqn)
- {
- ReentrantLock l = sharedLocks[hashToIndex(fqn)];
- if (trace) log.trace("Found lock " + l + " for fqn " +
fqn);
- return l;
- }
-
- public int getNumLocksHeld()
- {
- int i = 0;
- for (ReentrantLock l : sharedLocks) if (l.isLocked()) i++;
- return i;
- }
-
- boolean ownsLock(Fqn fqn, Object owner)
- {
- ReentrantLock lock = getLock(fqn);
- return lock.isHeldByCurrentThread();
- }
-
- boolean isLocked(Fqn fqn)
- {
- ReentrantLock lock = getLock(fqn);
- return lock.isLocked();
- }
-
- public String toString()
- {
- return "ReentrantLockContainer{" +
- "sharedLocks=" + (sharedLocks == null ? null :
Arrays.asList(sharedLocks)) +
- '}';
- }
- }
-
- public class OwnableReentrantLockContainer extends LockContainer
- {
- OwnableReentrantLock[] sharedLocks;
-
- void initLocks(int numLocks)
- {
- sharedLocks = new OwnableReentrantLock[numLocks];
- for (int i = 0; i < numLocks; i++) sharedLocks[i] = new
OwnableReentrantLock(invocationContextContainer);
- }
-
- OwnableReentrantLock getLock(Fqn fqn)
- {
- OwnableReentrantLock l = sharedLocks[hashToIndex(fqn)];
- if (trace) log.trace("Found lock " + l + " for fqn " +
fqn);
- return l;
- }
-
- boolean ownsLock(Fqn fqn, Object owner)
- {
- OwnableReentrantLock lock = getLock(fqn);
- return owner.equals(lock.getOwner());
- }
-
- boolean isLocked(Fqn fqn)
- {
- OwnableReentrantLock lock = getLock(fqn);
- return lock.isLocked();
- }
-
- public int getNumLocksHeld()
- {
- int i = 0;
- for (OwnableReentrantLock l : sharedLocks) if (l.isLocked()) i++;
- return i;
- }
-
- public String toString()
- {
- return "OwnableReentrantLockContainer{" +
- "sharedLocks=" + (sharedLocks == null ? null :
Arrays.asList(sharedLocks)) +
- '}';
- }
- }
}
Added: core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/LockContainer.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/LockContainer.java
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/LockContainer.java 2008-07-30
15:43:05 UTC (rev 6442)
@@ -0,0 +1,89 @@
+package org.jboss.cache.util.concurrent.locks;
+
+import net.jcip.annotations.ThreadSafe;
+
+import java.util.concurrent.locks.Lock;
+
+/**
+ * A container for locks. Used with lock striping.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+@ThreadSafe
+public abstract class LockContainer<E>
+{
+ private int lockSegmentMask;
+ private int lockSegmentShift;
+
+
+ protected int calculateNumberOfSegments(int concurrencyLevel)
+ {
+ int tempLockSegShift = 0;
+ int numLocks = 1;
+ while (numLocks < concurrencyLevel)
+ {
+ ++tempLockSegShift;
+ numLocks <<= 1;
+ }
+ lockSegmentShift = 32 - tempLockSegShift;
+ lockSegmentMask = numLocks - 1;
+ return numLocks;
+ }
+
+ public final int hashToIndex(E object)
+ {
+ return (hash(object) >>> lockSegmentShift) & lockSegmentMask;
+ }
+
+ /**
+ * Returns a hash code for non-null Object x.
+ * Uses the same hash code spreader as most other java.util hash tables, except that
this uses the string representation
+ * of the object passed in.
+ *
+ * @param object the object serving as a key
+ * @return the hash code
+ */
+ final int hash(E object)
+ {
+ int h = object.hashCode();
+ h += ~(h << 9);
+ h ^= (h >>> 14);
+ h += (h << 4);
+ h ^= (h >>> 10);
+ return h;
+ }
+
+ protected abstract void initLocks(int numLocks);
+
+ /**
+ * Tests if a give owner owns a lock on a specified object.
+ *
+ * @param object object to check
+ * @param owner owner to test
+ * @return true if owner owns lock, false otherwise
+ */
+ public abstract boolean ownsLock(E object, Object owner);
+
+ /**
+ * @param object object
+ * @return true if an object is locked, false otherwise
+ */
+ public abstract boolean isLocked(E object);
+
+ /**
+ * @param object object
+ * @return the lock for a specific object
+ */
+ public abstract Lock getLock(E object);
+
+ /**
+ * @return number of locks held
+ */
+ public abstract int getNumLocksHeld();
+
+ /**
+ * Clears all locks held and re-initialises stripes.
+ */
+ public abstract void reset();
+}
Modified:
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java 2008-07-30
15:42:20 UTC (rev 6441)
+++
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java 2008-07-30
15:43:05 UTC (rev 6442)
@@ -42,6 +42,8 @@
*/
public OwnableReentrantLock(InvocationContextContainer invocationContextContainer)
{
+ if (invocationContextContainer == null)
+ throw new IllegalArgumentException("Invocation context container cannot be
null!");
this.invocationContextContainer = invocationContextContainer;
}
Added:
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLockContainer.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLockContainer.java
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLockContainer.java 2008-07-30
15:43:05 UTC (rev 6442)
@@ -0,0 +1,75 @@
+package org.jboss.cache.util.concurrent.locks;
+
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.cache.invocation.InvocationContextContainer;
+
+import java.util.Arrays;
+
+/**
+ * A LockContainer that holds {@link
org.jboss.cache.util.concurrent.locks.OwnableReentrantLock}s.
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @see org.jboss.cache.util.concurrent.locks.ReentrantLockContainer
+ * @see org.jboss.cache.util.concurrent.locks.OwnableReentrantLock
+ * @since 3.0
+ */
+@ThreadSafe
+public class OwnableReentrantLockContainer<E> extends LockContainer<E>
+{
+ OwnableReentrantLock[] sharedLocks;
+ InvocationContextContainer icc;
+
+ /**
+ * Creates a new LockContainer which uses a certain number of shared locks across all
elements that need to be locked.
+ *
+ * @param concurrencyLevel concurrency level for number of stripes to create. Stripes
are created in powers of two, with a minimum of concurrencyLevel created.
+ * @param icc invocation context container to use
+ */
+ public OwnableReentrantLockContainer(int concurrencyLevel, InvocationContextContainer
icc)
+ {
+ this.icc = icc;
+ initLocks(calculateNumberOfSegments(concurrencyLevel));
+ }
+
+ protected void initLocks(int numLocks)
+ {
+ sharedLocks = new OwnableReentrantLock[numLocks];
+ for (int i = 0; i < numLocks; i++) sharedLocks[i] = new
OwnableReentrantLock(icc);
+ }
+
+ public final OwnableReentrantLock getLock(E object)
+ {
+ return sharedLocks[hashToIndex(object)];
+ }
+
+ public final boolean ownsLock(E object, Object owner)
+ {
+ OwnableReentrantLock lock = getLock(object);
+ return owner.equals(lock.getOwner());
+ }
+
+ public final boolean isLocked(E object)
+ {
+ OwnableReentrantLock lock = getLock(object);
+ return lock.isLocked();
+ }
+
+ public final int getNumLocksHeld()
+ {
+ int i = 0;
+ for (OwnableReentrantLock l : sharedLocks) if (l.isLocked()) i++;
+ return i;
+ }
+
+ public String toString()
+ {
+ return "OwnableReentrantLockContainer{" +
+ "sharedLocks=" + (sharedLocks == null ? null :
Arrays.asList(sharedLocks)) +
+ '}';
+ }
+
+ public void reset()
+ {
+ initLocks(sharedLocks.length);
+ }
+}
Added:
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/ReentrantLockContainer.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/ReentrantLockContainer.java
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/ReentrantLockContainer.java 2008-07-30
15:43:05 UTC (rev 6442)
@@ -0,0 +1,71 @@
+package org.jboss.cache.util.concurrent.locks;
+
+import net.jcip.annotations.ThreadSafe;
+
+import java.util.Arrays;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A LockContainer that holds ReentrantLocks
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @see org.jboss.cache.util.concurrent.locks.OwnableReentrantLockContainer
+ * @since 3.0
+ */
+@ThreadSafe
+public class ReentrantLockContainer<E> extends LockContainer<E>
+{
+ ReentrantLock[] sharedLocks;
+
+ /**
+ * Creates a new LockContainer which uses a certain number of shared locks across all
elements that need to be locked.
+ *
+ * @param concurrencyLevel concurrency level for number of stripes to create. Stripes
are created in powers of two, with a minimum of concurrencyLevel created.
+ */
+ public ReentrantLockContainer(int concurrencyLevel)
+ {
+ initLocks(calculateNumberOfSegments(concurrencyLevel));
+ }
+
+ protected void initLocks(int numLocks)
+ {
+ sharedLocks = new ReentrantLock[numLocks];
+ for (int i = 0; i < numLocks; i++) sharedLocks[i] = new ReentrantLock();
+ }
+
+ public final ReentrantLock getLock(E object)
+ {
+ return sharedLocks[hashToIndex(object)];
+ }
+
+ public final int getNumLocksHeld()
+ {
+ int i = 0;
+ for (ReentrantLock l : sharedLocks) if (l.isLocked()) i++;
+ return i;
+ }
+
+ public final boolean ownsLock(E object, Object owner)
+ {
+ ReentrantLock lock = getLock(object);
+ return lock.isHeldByCurrentThread();
+ }
+
+ public final boolean isLocked(E object)
+ {
+ ReentrantLock lock = getLock(object);
+ return lock.isLocked();
+ }
+
+ public String toString()
+ {
+ return "ReentrantLockContainer{" +
+ "sharedLocks=" + (sharedLocks == null ? null :
Arrays.asList(sharedLocks)) +
+ '}';
+ }
+
+ public void reset()
+ {
+ initLocks(sharedLocks.length);
+ }
+}
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockAssert.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockAssert.java 2008-07-30 15:42:20
UTC (rev 6441)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockAssert.java 2008-07-30 15:43:05
UTC (rev 6442)
@@ -3,8 +3,8 @@
import org.jboss.cache.Fqn;
import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.lock.LockManager;
-import org.jboss.cache.lock.MVCCLockManager.LockContainer;
import org.jboss.cache.util.TestingUtil;
+import org.jboss.cache.util.concurrent.locks.LockContainer;
/**
* Helper class to assert lock status in MVCC
Modified: core/trunk/src/test/java/org/jboss/cache/lock/MVCCLockManagerRecordingTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/lock/MVCCLockManagerRecordingTest.java 2008-07-30
15:42:20 UTC (rev 6441)
+++
core/trunk/src/test/java/org/jboss/cache/lock/MVCCLockManagerRecordingTest.java 2008-07-30
15:43:05 UTC (rev 6442)
@@ -4,9 +4,9 @@
import org.jboss.cache.config.Configuration;
import org.jboss.cache.factories.context.MVCCContextFactory;
import org.jboss.cache.invocation.InvocationContextContainer;
-import org.jboss.cache.lock.MVCCLockManager.LockContainer;
import org.jboss.cache.transaction.DummyTransactionManager;
import org.jboss.cache.util.TestingUtil;
+import org.jboss.cache.util.concurrent.locks.LockContainer;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
Show replies by date