package net.ossrs.yasea; import java.util.Arrays; public final class SrsAllocator { public class Allocation { private byte[] data; private int size; public Allocation(int size) { this.data = new byte[size]; this.size = 0; } public byte[] array() { return data; } public int size() { return size; } public void appendOffset(int offset) { size += offset; } public void clear() { size = 0; } public void put(byte b) { data[size++] = b; } public void put(byte b, int pos) { data[pos++] = b; size = pos > size ? pos : size; } public void put(short s) { put((byte) s); put((byte) (s >>> 8)); } public void put(int i) { put((byte) i); put((byte) (i >>> 8)); put((byte) (i >>> 16)); put((byte) (i >>> 24)); } public void put(byte[] bs) { System.arraycopy(bs, 0, data, size, bs.length); size += bs.length; } } private final int individualAllocationSize; private volatile int availableSentinel; private Allocation[] availableAllocations; /** * Constructs an instance without creating any {@link Allocation}s up front. * * @param individualAllocationSize The length of each individual {@link Allocation}. */ public SrsAllocator(int individualAllocationSize) { this(individualAllocationSize, 0); } /** * Constructs an instance with some {@link Allocation}s created up front. *

* * @param individualAllocationSize The length of each individual {@link Allocation}. * @param initialAllocationCount The number of allocations to create up front. */ public SrsAllocator(int individualAllocationSize, int initialAllocationCount) { this.individualAllocationSize = individualAllocationSize; this.availableSentinel = initialAllocationCount + 10; this.availableAllocations = new Allocation[availableSentinel]; for (int i = 0; i < availableSentinel; i++) { availableAllocations[i] = new Allocation(individualAllocationSize); } } public synchronized Allocation allocate(int size) { for (int i = 0; i < availableSentinel; i++) { if (availableAllocations[i].size() >= size) { Allocation ret = availableAllocations[i]; availableAllocations[i] = null; return ret; } } return new Allocation(size > individualAllocationSize ? size : individualAllocationSize); } public synchronized void release(Allocation allocation) { allocation.clear(); for (int i = 0; i < availableSentinel; i++) { if (availableAllocations[i].size() == 0) { availableAllocations[i] = allocation; return; } } if (availableSentinel + 1 > availableAllocations.length) { availableAllocations = Arrays.copyOf(availableAllocations, availableAllocations.length * 2); } availableAllocations[availableSentinel++] = allocation; } }