diff --git a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java index b9080a57d..4c1c4bb3f 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java @@ -56,6 +56,11 @@ public class LWJGLBufferAllocator implements BufferAllocator { stampedLock.unlockWrite(stamp); } } + + @Override + Deallocator createDeallocator(final Long address, final ByteBuffer byteBuffer) { + return new ConcurrentDeallocator(byteBuffer, DUMMY_QUEUE, address, stampedLock); + } } /** @@ -66,12 +71,12 @@ public class LWJGLBufferAllocator implements BufferAllocator { /** * The LWJGL byte buffer deallocator. */ - private static class Deallocator extends PhantomReference { + static class Deallocator extends PhantomReference { /** * The address of LWJGL byte buffer. */ - private volatile Long address; + volatile Long address; Deallocator(final ByteBuffer referent, final ReferenceQueue queue, final Long address) { super(referent, queue); @@ -90,9 +95,37 @@ public class LWJGLBufferAllocator implements BufferAllocator { */ void free() { if (address == null) return; - MemoryUtil.nmemFree(address); + freeMemory(); DEALLOCATORS.remove(address); } + + void freeMemory() { + MemoryUtil.nmemFree(address); + } + } + + /** + * The LWJGL byte buffer deallocator. + */ + static class ConcurrentDeallocator extends Deallocator { + + final StampedLock stampedLock; + + ConcurrentDeallocator(final ByteBuffer referent, final ReferenceQueue queue, + final Long address, final StampedLock stampedLock) { + super(referent, queue, address); + this.stampedLock = stampedLock; + } + + @Override + protected void freeMemory() { + final long stamp = stampedLock.writeLock(); + try { + super.freeMemory(); + } finally { + stampedLock.unlockWrite(stamp); + } + } } /** @@ -114,7 +147,7 @@ public class LWJGLBufferAllocator implements BufferAllocator { /** * Free unnecessary LWJGL byte buffers. */ - private static void freeByteBuffers() { + static void freeByteBuffers() { try { for (;;) { final Deallocator deallocator = (Deallocator) DUMMY_QUEUE.remove(); @@ -154,7 +187,7 @@ public class LWJGLBufferAllocator implements BufferAllocator { * @param buffer the buffer. * @return the address or -1. */ - private long getAddress(final Buffer buffer) { + long getAddress(final Buffer buffer) { if (buffer instanceof ByteBuffer) { return MemoryUtil.memAddress((ByteBuffer) buffer, 0); @@ -179,7 +212,11 @@ public class LWJGLBufferAllocator implements BufferAllocator { public ByteBuffer allocate(final int size) { final Long address = MemoryUtil.nmemAlloc(size); final ByteBuffer byteBuffer = MemoryUtil.memByteBuffer(address, size); - DEALLOCATORS.put(address, new Deallocator(byteBuffer, DUMMY_QUEUE, address)); + DEALLOCATORS.put(address, createDeallocator(address, byteBuffer)); return byteBuffer; } + + Deallocator createDeallocator(final Long address, final ByteBuffer byteBuffer) { + return new Deallocator(byteBuffer, DUMMY_QUEUE, address); + } }