package org.infinispan.container.offheap; import java.util.concurrent.atomic.AtomicLong; import java.util.function.LongUnaryOperator; import org.infinispan.factories.annotations.Inject; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; import sun.misc.Unsafe; /** * Memory allocator that just allocates memory directly using {@link Unsafe}. * @author wburns * @since 9.0 */ public class UnpooledOffHeapMemoryAllocator implements OffHeapMemoryAllocator { private static final Unsafe UNSAFE = UnsafeHolder.UNSAFE; private static final Log log = LogFactory.getLog(UnpooledOffHeapMemoryAllocator.class, Log.class); private static final boolean trace = log.isTraceEnabled(); private final AtomicLong amountAllocated = new AtomicLong(); private LongUnaryOperator sizeCalculator; @Inject public void inject(OffHeapEntryFactory offHeapEntryFactory) { sizeCalculator = offHeapEntryFactory::determineSize; } @Override public long allocate(long memoryLength) { long memoryLocation = UNSAFE.allocateMemory(memoryLength); long currentSize = amountAllocated.addAndGet(memoryLength); if (trace) { log.tracef("Allocated off heap memory at %d with %d bytes. Total size: %d", memoryLocation, memoryLength, currentSize); } return memoryLocation; } @Override public void deallocate(long memoryAddress) { deallocate(memoryAddress, sizeCalculator.applyAsLong(memoryAddress)); } @Override public void deallocate(long memoryAddress, long size) { long currentSize = amountAllocated.addAndGet(- size); if (trace) { log.tracef("Deallocating off heap memory at %d with %d bytes. Total size: %d", memoryAddress, size, currentSize); } UNSAFE.freeMemory(memoryAddress); } @Override public long getAllocatedAmount() { return amountAllocated.get(); } }