Merge pull request #393 from olegz/INT-2502-patch
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user