diff --git a/akka-io/src/main/scala/akka/io/DirectByteBufferPool.scala b/akka-io/src/main/scala/akka/io/DirectByteBufferPool.scala index 103be7bf6a..ed9ed4d175 100644 --- a/akka-io/src/main/scala/akka/io/DirectByteBufferPool.scala +++ b/akka-io/src/main/scala/akka/io/DirectByteBufferPool.scala @@ -3,7 +3,6 @@ package akka.io import java.util.concurrent.atomic.AtomicBoolean import java.nio.ByteBuffer import annotation.tailrec -import java.lang.ref.SoftReference trait WithBufferPool { def tcp: TcpExt @@ -29,20 +28,11 @@ trait BufferPool { */ private[akka] class DirectByteBufferPool(defaultBufferSize: Int, maxPoolEntries: Int) extends BufferPool { private[this] val locked = new AtomicBoolean(false) - private[this] val pool: Array[SoftReference[ByteBuffer]] = new Array[SoftReference[ByteBuffer]](maxPoolEntries) + private[this] val pool: Array[ByteBuffer] = new Array[ByteBuffer](maxPoolEntries) private[this] var buffersInPool: Int = 0 - def acquire(): ByteBuffer = { - val buffer = takeBufferFromPool() - - // allocate new buffer and clear outside the lock - if (buffer == null) - allocate(defaultBufferSize) - else { - buffer.clear() - buffer - } - } + def acquire(): ByteBuffer = + takeBufferFromPool() def release(buf: ByteBuffer): Unit = offerBufferToPool(buf) @@ -51,26 +41,29 @@ private[akka] class DirectByteBufferPool(defaultBufferSize: Int, maxPoolEntries: ByteBuffer.allocateDirect(size) @tailrec - private[this] final def takeBufferFromPool(): ByteBuffer = { - @tailrec def findBuffer(): ByteBuffer = - if (buffersInPool > 0) { - buffersInPool -= 1 - val buf = pool(buffersInPool).get() + private final def takeBufferFromPool(): ByteBuffer = + if (locked.compareAndSet(false, true)) { + val buffer = + try if (buffersInPool > 0) { + buffersInPool -= 1 + pool(buffersInPool) + } else null + finally locked.set(false) - if (buf != null) buf - else findBuffer() - } else null - - if (locked.compareAndSet(false, true)) - try findBuffer() finally locked.set(false) - else takeBufferFromPool() // spin while locked - } + // allocate new and clear outside the lock + if (buffer == null) + allocate(defaultBufferSize) + else { + buffer.clear() + buffer + } + } else takeBufferFromPool() // spin while locked @tailrec private final def offerBufferToPool(buf: ByteBuffer): Unit = if (locked.compareAndSet(false, true)) try if (buffersInPool < maxPoolEntries) { - pool(buffersInPool) = new SoftReference(buf) + pool(buffersInPool) = buf buffersInPool += 1 } // else let the buffer be gc'd finally locked.set(false)