org.infinispan.container.offheap.MemoryAddressHash Maven / Gradle / Ivy
package org.infinispan.container.offheap;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import sun.misc.Unsafe;
/**
* @author wburns
* @since 9.0
*/
public class MemoryAddressHash {
private static final Unsafe UNSAFE = UnsafeHolder.UNSAFE;
private static final int MAXIMUM_CAPACITY = 1 << 30;
private static final int HASH_BITS = 0x7fffffff; // usable bits of normal node hash
private final long memory;
private final int pointerCount;
public MemoryAddressHash(int pointers) {
this.pointerCount = nextPowerOfTwo(pointers);
long bytes = ((long) pointerCount) << 3;
memory = UNSAFE.allocateMemory(bytes);
// Have to clear out bytes to make sure no bad stuff was read in
UNSAFE.setMemory(memory, bytes, (byte) 0);
}
private int findOffset(Object instance) {
int h = spread(instance.hashCode());
int pointerMask = pointerCount - 1;
return h & pointerMask;
}
public void putMemoryAddress(Object instance, long address) {
int offset = findOffset(instance);
UNSAFE.putLong(memory + (((long) offset) << 3), address);
}
public long getMemoryAddress(Object instance) {
return UNSAFE.getLong(memory + (findOffset(instance) << 3));
}
public long getMemoryAddressOffset(int offset) {
return UNSAFE.getLong(memory + (((long) offset) << 3));
}
public void deallocate() {
UNSAFE.freeMemory(memory);
}
/**
* Returns a stream of longs that are all of the various memory locations
* @return stream of the various memory locations
*/
public LongStream toStream() {
return LongStream.iterate(memory, l -> l + 8)
.limit(pointerCount)
.map(UNSAFE::getLong)
.filter(l -> l != 0);
}
/**
* Same as {@link MemoryAddressHash#toStream()} except that the memory addresses are also cleared out (set to 0)
* @return stream with the valid memory pointers to stored values
*/
public LongStream toStreamRemoved() {
return LongStream.iterate(memory, l -> l + 8)
.limit(pointerCount)
.map(l -> UNSAFE.getAndSetLong(null, l, 0))
.filter(l -> l != 0);
}
private static final int nextPowerOfTwo(int c) {
int n = c - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
static final int spread(int h) {
return (h ^ (h >>> 16)) & HASH_BITS;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy