Author: manik.surtani(a)jboss.com
Date: 2008-01-03 19:48:28 -0500 (Thu, 03 Jan 2008)
New Revision: 4969
Added:
core/trunk/src/main/java/org/jboss/cache/util/BitEncodedIntegerSet.java
core/trunk/src/test/java/org/jboss/cache/util/BitEncodedIntegerSetTest.java
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java
Log:
Moved bit encoding of method ints into separate utility class
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java 2008-01-03
19:17:09 UTC (rev 4968)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/MethodDispacherInterceptor.java 2008-01-04
00:48:28 UTC (rev 4969)
@@ -8,6 +8,7 @@
import org.jboss.cache.marshall.MethodDeclarations;
import org.jboss.cache.optimistic.DataVersion;
import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.util.BitEncodedIntegerSet;
import org.jgroups.Address;
import java.util.List;
@@ -34,22 +35,15 @@
public abstract class MethodDispacherInterceptor extends Interceptor
{
/**
- * Methods that have been overridden. This is encoded in the bits of an integer, with
each ordinal position representing a method id.
- * This was originally a Set but that proved way too inefficient with constant
boxing/unboxing of ints and doing Set.contains()
- * for each invocation for each interceptor. - Manik, Jan '08.
+ * Methods that have been overridden.
*/
- private long overriddenMethods = 0;
+ private BitEncodedIntegerSet overriddenMethods = new BitEncodedIntegerSet();
protected MethodDispacherInterceptor()
{
findOverriddenMethods();
}
- private boolean noHandlersRegistered(int id)
- {
- return (overriddenMethods & ((long) 1 << id)) < 1;
- }
-
/**
* Acts like a 'switch case' that delegates the call to the appropriate
method.
*/
@@ -62,7 +56,7 @@
return nextInterceptor(ctx);
}
MethodCall m = ctx.getMethodCall();
- if (noHandlersRegistered(m.getMethodId()))
+ if (!overriddenMethods.contains(m.getMethodId()))
{
if (trace) log.trace("Not registered for any handlers, passing up the
chain.");
return nextInterceptor(ctx);
@@ -524,7 +518,7 @@
try
{
currentClass.getDeclaredMethod(methodName, args);
- overriddenMethods |= ((long) 1 << methodId);
+ overriddenMethods.add(methodId);
}
catch (NoSuchMethodException e)
{
Added: core/trunk/src/main/java/org/jboss/cache/util/BitEncodedIntegerSet.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/BitEncodedIntegerSet.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/util/BitEncodedIntegerSet.java 2008-01-04
00:48:28 UTC (rev 4969)
@@ -0,0 +1,92 @@
+package org.jboss.cache.util;
+
+import net.jcip.annotations.NotThreadSafe;
+
+/**
+ * A Set that encodes integers as bits in a long. Does not implement java.util.Set since
autoboxing is unnecessarily
+ * expensive for the ints stored, but follows very similar semantics to Set: no nulls, no
duplicates, and order not guaranteed,
+ * and adds one more: this can only store ints from 0 to 63, inclusive.
+ * <p/>
+ * Integers in this set are packed into a single long, setting bit values accordingly and
hence the strict range on allowable
+ * integers. The upshot is a guaranteed limit on how much memory is consumed, as well as
very efficient operations on the set.
+ * <p/>
+ *
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.1.0
+ */
+@NotThreadSafe
+public class BitEncodedIntegerSet
+{
+ private long encoded = 0;
+
+ /**
+ * Adds an integer to the set.
+ *
+ * @param i integer to add
+ */
+ public void add(int i)
+ {
+ encoded |= ((long) 1 << i);
+ }
+
+ /**
+ * Removes an integer from the set
+ *
+ * @param i integer to remove
+ */
+ public void remove(int i)
+ {
+ encoded &= ~((long) 1 << i);
+ }
+
+ /**
+ * Tests whether the set contains an integer
+ *
+ * @param i integer to check for
+ * @return true if contained; false otherwise
+ */
+ public boolean contains(int i)
+ {
+ return (encoded & ((long) 1 << i)) != 0;
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BitEncodedIntegerSet that = (BitEncodedIntegerSet) o;
+
+ return encoded == that.encoded;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return (int) (encoded ^ (encoded >>> 32));
+ }
+
+ /**
+ * Clears the set
+ */
+ public void clear()
+ {
+ encoded = 0;
+ }
+
+ /**
+ * Tests if the set is empty
+ *
+ * @return true if empty
+ */
+ public boolean isEmpty()
+ {
+ return encoded == 0;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BitEncodedSet (encoded as: " + Long.toBinaryString(encoded) +
")";
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/util/BitEncodedIntegerSetTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/BitEncodedIntegerSetTest.java
(rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/util/BitEncodedIntegerSetTest.java 2008-01-04
00:48:28 UTC (rev 4969)
@@ -0,0 +1,113 @@
+package org.jboss.cache.util;
+
+import org.testng.annotations.Test;
+
+/**
+ * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
+ * @since 2.1.0
+ */
+@Test(groups = "functional")
+public class BitEncodedIntegerSetTest
+{
+ public void testLimits()
+ {
+ BitEncodedIntegerSet set = new BitEncodedIntegerSet();
+ set.add(0);
+ set.add(1);
+ set.add(62);
+ set.add(63);
+
+ for (int i = 0; i < 64; i++)
+ {
+ if (i == 0 || i == 1 || i == 62 || i == 63)
+ {
+ assert set.contains(i) : "Should contain " + i;
+ }
+ else
+ {
+ assert !set.contains(i) : "Should not contain " + i;
+ }
+ }
+ }
+
+ public void testRemoval()
+ {
+ BitEncodedIntegerSet set = new BitEncodedIntegerSet();
+ set.add(0);
+ set.add(1);
+ set.add(62);
+ set.add(63);
+
+ set.remove(0);
+ set.remove(63);
+
+ for (int i = 0; i < 64; i++)
+ {
+ if (i == 1 || i == 62)
+ {
+ assert set.contains(i);
+ }
+ else
+ {
+ assert !set.contains(i);
+ }
+ }
+
+ }
+
+ public void testClear()
+ {
+ BitEncodedIntegerSet set = new BitEncodedIntegerSet();
+ set.add(0);
+ set.add(1);
+ set.add(62);
+ set.add(63);
+
+ for (int i = 0; i < 64; i++)
+ {
+ if (i == 0 || i == 1 || i == 62 || i == 63)
+ {
+ assert set.contains(i);
+ }
+ else
+ {
+ assert !set.contains(i);
+ }
+ }
+ set.clear();
+
+ assert set.isEmpty();
+ }
+
+ public void testIsEmpty()
+ {
+ BitEncodedIntegerSet set = new BitEncodedIntegerSet();
+ assert set.isEmpty();
+ }
+
+ public void testEquals()
+ {
+ BitEncodedIntegerSet set1 = new BitEncodedIntegerSet();
+ BitEncodedIntegerSet set2 = new BitEncodedIntegerSet();
+
+ assert set1.equals(set2);
+ assert set2.equals(set1);
+
+ set1.add(1);
+
+ assert !set1.equals(set2);
+ assert !set2.equals(set1);
+
+ set2.add(1);
+
+ assert set1.equals(set2);
+ assert set2.equals(set1);
+
+ set2.add(2);
+
+ assert !set1.equals(set2);
+ assert !set2.equals(set1);
+ }
+
+
+}