Author: manik.surtani(a)jboss.com
Date: 2008-06-24 11:23:45 -0400 (Tue, 24 Jun 2008)
New Revision: 6014
Added:
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java
Log:
Added OwnableReentrantLock
Added:
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
(rev 0)
+++
core/trunk/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java 2008-06-24
15:23:45 UTC (rev 6014)
@@ -0,0 +1,188 @@
+package org.jboss.cache.util.concurrent.locks;
+
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.cache.invocation.InvocationContextContainer;
+import org.jboss.cache.transaction.GlobalTransaction;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.Lock;
+
+/**
+ * A lock that supports reentrancy based on owner (and not on current thread). For this
to work, the lock needs to be
+ * constructed with a reference to the {@link
org.jboss.cache.invocation.InvocationContextContainer}, so it is able
+ * to determine whether the caller's "owner" reference is the current
thread or a {@link org.jboss.cache.transaction.GlobalTransaction}
+ * instance.
+ * <p/>
+ * This makes this lock implementation very closely tied to JBoss Cache internals, but it
provides for a very clean, efficient
+ * and moreover familiar interface to work with, since it implements {@link
java.util.concurrent.locks.Lock}.
+ * <p/>
+ * For the sake of performance, this lock only supports nonfair queueing.
+ * <p/>
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 3.0
+ */
+@ThreadSafe
+public class OwnableReentrantLock extends AbstractQueuedSynchronizer implements Lock
+{
+ /**
+ * Current owner
+ */
+ transient Object owner;
+ /**
+ * Invocation context to consult when testing the current requestor
+ */
+ transient InvocationContextContainer invocationContextContainer;
+
+ /**
+ * Creates a new lock instance.
+ *
+ * @param invocationContextContainer InvocationContextContainer instance to consult
for the invocation context of the call.
+ */
+ public OwnableReentrantLock(InvocationContextContainer invocationContextContainer)
+ {
+ this.invocationContextContainer = invocationContextContainer;
+ }
+
+ /**
+ * @return a GlobalTransaction instance if the current call is participating in a
transaction, or the current thread otherwise.
+ */
+ protected Object currentRequestor()
+ {
+ GlobalTransaction gtx;
+ return (gtx = invocationContextContainer.get().getGlobalTransaction()) == null ?
Thread.currentThread() : gtx;
+ }
+
+ public void lock()
+ {
+ if (compareAndSetState(0, 1))
+ owner = currentRequestor();
+ else
+ acquire(1);
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ acquireInterruptibly(1);
+ }
+
+ public boolean tryLock()
+ {
+ return tryAcquire(1);
+ }
+
+ public boolean tryLock(long time, TimeUnit unit) throws InterruptedException
+ {
+ return tryAcquireNanos(1, unit.toNanos(time));
+ }
+
+ public void unlock()
+ {
+ release(1);
+ }
+
+ public final ConditionObject newCondition()
+ {
+ return new ConditionObject();
+ }
+
+ @Override
+ protected final boolean tryAcquire(int acquires)
+ {
+ final Object current = currentRequestor();
+ int c = getState();
+ if (c == 0)
+ {
+ if (compareAndSetState(0, acquires))
+ {
+ owner = current;
+ return true;
+ }
+ }
+ else if (current.equals(owner))
+ {
+ setState(c + acquires);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected final boolean tryRelease(int releases)
+ {
+ int c = getState() - releases;
+ if (!currentRequestor().equals(owner))
+ throw new IllegalMonitorStateException();
+ boolean free = false;
+ if (c == 0)
+ {
+ free = true;
+ owner = null;
+ }
+ setState(c);
+ return free;
+ }
+
+ @Override
+ protected final boolean isHeldExclusively()
+ {
+ return getState() != 0 && currentRequestor().equals(owner);
+ }
+
+ /**
+ * @return the owner of the lock, or null if it is currently unlocked.
+ */
+ public final Object getOwner()
+ {
+ int c = getState();
+ Object o = owner;
+ return (c == 0) ? null : o;
+ }
+
+ /**
+ * @return the hold count of the current lock, or 0 if it is not locked.
+ */
+ public final int getHoldCount()
+ {
+ int c = getState();
+ Object o = owner;
+ return (currentRequestor().equals(o)) ? c : 0;
+ }
+
+ /**
+ * @return true if the lock is locked, false otherwise
+ */
+ public final boolean isLocked()
+ {
+ return getState() != 0;
+ }
+
+ /**
+ * Reconstitute this lock instance from a stream, resetting the lock to an unlocked
state.
+ *
+ * @param s the stream
+ */
+ private void readObject(java.io.ObjectInputStream s)
+ throws java.io.IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ setState(0); // reset to unlocked state
+ }
+
+ /**
+ * Returns a string identifying this lock, as well as its lock
+ * state. The state, in brackets, includes either the String
+ * "Unlocked" or the String "Locked by"
+ * followed by the String representation of the lock owner.
+ *
+ * @return a string identifying this lock, as well as its lock state.
+ */
+ public String toString()
+ {
+ Object owner = getOwner();
+ return super.toString() + ((owner == null) ?
+ "[Unlocked]" :
+ "[Locked by " + owner + "]");
+ }
+}
Show replies by date