/**
* Copyright 2024 Beijing Baolande Software Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Runtime Library Exception to the Apache 2.0 License:
*
* As an exception, if you use this Software to compile your source code and
* portions of this Software are embedded into the binary product as a result,
* you may redistribute such product without providing attribution as would
* otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.
*/
package hyperion.buffer
/**
* ByteBuffer分配器
*
* @author yangfuping
*/
public abstract class ByteBufferAllocator <: Equatable<ByteBufferAllocator> {
protected static let logger = LoggerFactory.getLogger("transport")
protected static let idGen = AtomicInt64(0)
protected let createTime = DateTime.now()
protected let id = idGen.fetchAdd(1)
protected let allocateSize: Int64
public init(allocateSize: Int64) {
if (allocateSize < 0) {
throw IllegalArgumentException("Negative allocate size ${allocateSize}")
}
this.allocateSize = allocateSize
}
public open func allocate(): ByteBuffer
public open func allocate(capacity: Int64): ByteBuffer
public open func allocate(capacity: Int64, expandSupport: Bool): ByteBuffer
public open func free(buffer: ?ByteBuffer): Unit
}
/**
* 不带池化的ArrayByteBuffer分配器
*
* @author yangfuping
*/
public open class ArrayByteBufferAllocator <: ByteBufferAllocator {
private let expandSupport: Bool
public init() {
super(ByteBuffer.DEFAULT_INITIAL_CAPACITY)
// 默认支持扩展
this.expandSupport = true
}
public init(allocateSize: Int64) {
super(allocateSize)
// 默认支持扩展
this.expandSupport = true
}
public init(allocateSize: Int64, expandSupport: Bool) {
super(allocateSize)
this.expandSupport = expandSupport
}
public open func allocate(): ByteBuffer {
return allocate(allocateSize)
}
public open func allocate(capacity: Int64): ArrayByteBuffer {
var realAllocateSize = capacity
if (capacity < allocateSize) {
// 需要的空间小于allocateSize, 按allocateSize分配
realAllocateSize = allocateSize
}
return ArrayByteBuffer(realAllocateSize, expandSupport: expandSupport)
}
public open func allocate(capacity: Int64, expandSupport: Bool): ArrayByteBuffer {
var realAllocateSize = capacity
if (capacity < allocateSize) {
// 需要的空间小于allocateSize, 按allocateSize分配
realAllocateSize = allocateSize
}
return ArrayByteBuffer(realAllocateSize, expandSupport: expandSupport)
}
public open func free(buffer: ?ByteBuffer): Unit {
// do nothing
}
public open operator func ==(other: ByteBufferAllocator): Bool {
if (let Some(buffer) <- (other as ArrayByteBufferAllocator)) {
if (id != buffer.id) {
return false
}
if (createTime != buffer.createTime) {
return false
}
return true
}
return false
}
public open operator func !=(other: ByteBufferAllocator): Bool {
if (let Some(buffer) <- (other as ArrayByteBufferAllocator)) {
if (id != buffer.id) {
return true
}
if (createTime != buffer.createTime) {
return true
}
return false
}
return true
}
}
/**
* 池化的ArrayByteBuffer分配器
*
* @author yangfuping
*/
public open class PooledArrayByteBufferAllocator <: ArrayByteBufferAllocator {
static let DEFAULT_POOLED_BUFFER_CAPACITY = 8192
static let DEFAULT_MAX_POOLED_BUFFERS = 2048
private let maxPooledBuffers: Int64
private let queue: ArrayBlockingQueue<ArrayByteBuffer>
public init() {
super(DEFAULT_POOLED_BUFFER_CAPACITY)
this.maxPooledBuffers = DEFAULT_MAX_POOLED_BUFFERS
queue = ArrayBlockingQueue<ArrayByteBuffer>(maxPooledBuffers)
}
public init(allocateSize: Int64, maxPooledBuffers: Int64) {
super(allocateSize)
this.maxPooledBuffers = maxPooledBuffers
queue = ArrayBlockingQueue<ArrayByteBuffer>(maxPooledBuffers)
}
public open func allocate(): ByteBuffer {
return allocate(allocateSize)
}
public open func allocate(capacity: Int64): ArrayByteBuffer {
if (capacity <= allocateSize) {
if (let Some(buffer) <- queue.tryRemove()) {
buffer.retain()
return buffer
}
//未从队列中取到值,直接创建
let refCounted = ReferenceCounted()
let buffer = ArrayByteBuffer(allocateSize, expandSupport: false, allocator: this, refCounted: refCounted)
refCounted.setDelegateBuffer(buffer)
// 增加引用数
buffer.retain()
if (logger.isTraceEnabled()) {
logger.log(LogLevel.TRACE, "Create Pooled ByteBuffer: ${buffer}, queue size: ${queue.size}")
}
return buffer
} else {
// 容量超出从allocateSize,直接创建
let buffer = ArrayByteBuffer(capacity)
if (logger.isTraceEnabled()) {
logger.log(LogLevel.TRACE, "Create UnPooled ByteBuffer: ${buffer}, queue size: ${queue.size}")
}
return buffer
}
}
public open func allocate(capacity: Int64, expandSupport: Bool): ArrayByteBuffer {
if (capacity <= allocateSize && !expandSupport) {
if (let Some(buffer) <- queue.tryRemove()) {
// 增加引用数
buffer.retain()
return buffer
}
let refCounted = ReferenceCounted()
let buffer = ArrayByteBuffer(allocateSize, expandSupport: false, allocator: this, refCounted: refCounted)
refCounted.setDelegateBuffer(buffer)
// 增加引用数
buffer.retain()
if (logger.isTraceEnabled()) {
logger.log(LogLevel.TRACE, "Create Pooled ByteBuffer: ${buffer}, queue size: ${queue.size}")
}
return buffer
}
// 容量超出从allocateSize,或者需要扩展的ByteBuffer,直接创建
let buffer = ArrayByteBuffer(capacity, expandSupport: expandSupport)
if (logger.isTraceEnabled()) {
logger.log(LogLevel.TRACE, "Create UnPooled ByteBuffer: ${buffer}, queue size: ${queue.size}")
}
return buffer
}
protected open func returnBuffer(buffer: ArrayByteBuffer): Unit {
if (queue.size < maxPooledBuffers) {
// 加入队列重新利用
if (queue.tryAdd(buffer)) {
if (logger.isTraceEnabled()) {
logger.log(LogLevel.TRACE, "Return Pooled ByteBuffer: ${buffer}, queue size: ${queue.size}")
}
}
}
}
public open func free(buffer: ?ByteBuffer): Unit {
if (let Some(buffer) <- buffer) {
if (let Some(arryByteBuffer) <- (buffer as ArrayByteBuffer)) {
if (let Some(allocator) <- buffer.getAllocator()) {
if (allocator == this) {
arryByteBuffer.free()
returnBuffer(arryByteBuffer)
}
}
}
}
}
public operator func ==(other: ByteBufferAllocator): Bool {
if (let Some(buffer) <- (other as PooledArrayByteBufferAllocator)) {
if (id != buffer.id) {
return false
}
if (createTime != buffer.createTime) {
return false
}
return true
}
return false
}
public operator func !=(other: ByteBufferAllocator): Bool {
if (let Some(buffer) <- (other as PooledArrayByteBufferAllocator)) {
if (id != buffer.id) {
return true
}
if (createTime != buffer.createTime) {
return true
}
return false
}
return true
}
}