Merge pull request #393 from olegz/INT-2502-patch

This commit is contained in:
Gary Russell
2012-03-29 11:22:47 -04:00
3 changed files with 153 additions and 136 deletions

View File

@@ -36,26 +36,26 @@ public final class DefaultLockRegistry implements LockRegistry {
private final int mask;
/**
* Constructs a DefaultLockRegistry with the default
* mask 0xFF with 256 locks.
*/
* Constructs a DefaultLockRegistry with the default
* mask 0xFF with 256 locks.
*/
public DefaultLockRegistry(){
this(0xFF);
}
/**
* Constructs a DefaultLockRegistry with the supplied
* mask - the mask must have a value (2**n) - 1 where n
* is 1 to 31, creating a hash of 2**n locks.
* <p> Examples:
* <li>0x3ff (1023) - 1024 locks</li>
* <li>0xfff (4095) - 4096 locks</li>
* <p>
* @param mask
*/
* Constructs a DefaultLockRegistry with the supplied
* mask - the mask must have a value Math.pow(2, n) - 1 where n
* is 1 to 31, creating a hash of Math.pow(2, n) locks.
* <p> Examples:
* <li>0x3ff (1023) - 1024 locks</li>
* <li>0xfff (4095) - 4096 locks</li>
* <p>
* @param mask
*/
public DefaultLockRegistry(int mask){
String bits = Integer.toBinaryString(mask);
Assert.isTrue(bits.lastIndexOf('0') < bits.indexOf('1'), "Mask must be a power of 2 - 1");
Assert.isTrue(bits.length() < 32 && (mask == 0 || bits.lastIndexOf('0') < bits.indexOf('1') ), "Mask must be a power of 2 - 1");
this.mask = mask;
int arraySize = this.mask+1;
lockTable = new ReentrantLock[arraySize];
@@ -65,10 +65,10 @@ public final class DefaultLockRegistry implements LockRegistry {
}
/**
* Obtains a lock by masking the lockKey's hashCode() with
* the mask and using the result as an index to the lock table.
* @param lockKey the object used to derive the lock index.
*/
* Obtains a lock by masking the lockKey's hashCode() with
* the mask and using the result as an index to the lock table.
* @param lockKey the object used to derive the lock index.
*/
public Lock obtain(Object lockKey) {
Assert.notNull(lockKey, "'lockKey' must not be null");
Integer lockIndex = lockKey.hashCode() & this.mask;

View File

@@ -24,10 +24,10 @@ import java.util.concurrent.locks.Lock;
public interface LockRegistry {
/**
* Obtains the lock associated with the parameter object.
* @param lockRoot The object with which the lock is associated.
* @return The associated lock.
*/
* Obtains the lock associated with the parameter object.
* @param lockKey The object with which the lock is associated.
* @return The associated lock.
*/
Lock obtain(Object lockKey);
}

View File

@@ -24,144 +24,161 @@ import org.junit.Test;
/**
* @author Gary Russell
* @author Oleg Zhurakousky
* @since 2.1.1
*
*/
public class DefaultLockRegistryTests {
@Test(expected=IllegalArgumentException.class)
public void testBadMask() {
new DefaultLockRegistry(4);
}
@Test(expected=IllegalArgumentException.class)
public void testBadMask() {
new DefaultLockRegistry(4);
}
@Test
public void testSame() {
LockRegistry registry = new DefaultLockRegistry();
Lock lock1 = registry.obtain(new Object() {
@Test(expected=IllegalArgumentException.class)
public void testBadMaskOutOfRange() {// 32bits
new DefaultLockRegistry(0xffffffff);
}
@Override
public int hashCode() {
return 0;
}});
Lock lock2 = registry.obtain(new Object() {
@Test
public void testSingleLockCreation() {
LockRegistry registry = new DefaultLockRegistry(0);
Lock a = registry.obtain(23);
Lock b = registry.obtain(new Object());
Lock c = registry.obtain("hello");
assertSame(a, b);
assertSame(a, c);
assertSame(b, c);
}
@Override
public int hashCode() {
return 256;
}});
assertSame(lock1, lock2);
}
@Test
public void testSame() {
LockRegistry registry = new DefaultLockRegistry();
Lock lock1 = registry.obtain(new Object() {
@Test
public void testDifferent() {
LockRegistry registry = new DefaultLockRegistry();
Lock lock1 = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
Lock lock2 = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
Lock lock2 = registry.obtain(new Object() {
@Override
public int hashCode() {
return 256;
}});
assertSame(lock1, lock2);
}
@Override
public int hashCode() {
return 255;
}});
assertNotSame(lock1, lock2);
}
@Test
public void testDifferent() {
LockRegistry registry = new DefaultLockRegistry();
Lock lock1 = registry.obtain(new Object() {
@Test
public void testAllDifferentAndSame() {
LockRegistry registry = new DefaultLockRegistry(3);
Lock[] locks = new Lock[4];
locks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
Lock lock2 = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
locks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 255;
}});
assertNotSame(lock1, lock2);
}
@Override
public int hashCode() {
return 1;
}});
locks[2] = registry.obtain(new Object() {
@Test
public void testAllDifferentAndSame() {
LockRegistry registry = new DefaultLockRegistry(3);
Lock[] locks = new Lock[4];
locks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 2;
}});
locks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
locks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 3;
}});
for (int i = 0; i < 4; i++) {
for (int j = 1; j < 4; j++) {
if (i != j) {
assertNotSame(locks[i], locks[j]);
}
}
}
Lock[] moreLocks = new Lock[4];
moreLocks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 1;
}});
locks[2] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
moreLocks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 2;
}});
locks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 1;
}});
moreLocks[2] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 3;
}});
for (int i = 0; i < 4; i++) {
for (int j = 1; j < 4; j++) {
if (i != j) {
assertNotSame(locks[i], locks[j]);
}
}
}
Lock[] moreLocks = new Lock[4];
moreLocks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 2;
}});
moreLocks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 0;
}});
moreLocks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 3;
}});
assertSame(locks[0], moreLocks[0]);
assertSame(locks[1], moreLocks[1]);
assertSame(locks[2], moreLocks[2]);
assertSame(locks[3], moreLocks[3]);
moreLocks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 1;
}});
moreLocks[2] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 4;
}});
moreLocks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 2;
}});
moreLocks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 5;
}});
moreLocks[2] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 3;
}});
assertSame(locks[0], moreLocks[0]);
assertSame(locks[1], moreLocks[1]);
assertSame(locks[2], moreLocks[2]);
assertSame(locks[3], moreLocks[3]);
moreLocks[0] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 6;
}});
moreLocks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 4;
}});
moreLocks[1] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 7;
}});
assertSame(locks[0], moreLocks[0]);
assertSame(locks[1], moreLocks[1]);
assertSame(locks[2], moreLocks[2]);
assertSame(locks[3], moreLocks[3]);
}
@Override
public int hashCode() {
return 5;
}});
moreLocks[2] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 6;
}});
moreLocks[3] = registry.obtain(new Object() {
@Override
public int hashCode() {
return 7;
}});
assertSame(locks[0], moreLocks[0]);
assertSame(locks[1], moreLocks[1]);
assertSame(locks[2], moreLocks[2]);
assertSame(locks[3], moreLocks[3]);
}
}