All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.netty.handler.codec.CodecOutputList Maven / Gradle / Ivy
/*
* Copyright 2016 The Netty Project
*
* The Netty Project licenses this file to you 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:
*
* https://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.
*/
package io.netty.handler.codec;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.MathUtil;
import java.util.AbstractList;
import java.util.RandomAccess;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
/**
* Special {@link AbstractList} implementation which is used within our codec base classes.
*/
final class CodecOutputList extends AbstractList implements RandomAccess {
private static final CodecOutputListRecycler NOOP_RECYCLER = new CodecOutputListRecycler() {
@Override
public void recycle(CodecOutputList object) {
// drop on the floor and let the GC handle it.
}
};
private static final FastThreadLocal CODEC_OUTPUT_LISTS_POOL =
new FastThreadLocal() {
@Override
protected CodecOutputLists initialValue() throws Exception {
// 16 CodecOutputList per Thread are cached.
return new CodecOutputLists(16);
}
};
private interface CodecOutputListRecycler {
void recycle(CodecOutputList codecOutputList);
}
private static final class CodecOutputLists implements CodecOutputListRecycler {
private final CodecOutputList[] elements;
private final int mask;
private int currentIdx;
private int count;
CodecOutputLists(int numElements) {
elements = new CodecOutputList[MathUtil.safeFindNextPositivePowerOfTwo(numElements)];
for (int i = 0; i < elements.length; ++i) {
// Size of 16 should be good enough for the majority of all users as an initial capacity.
elements[i] = new CodecOutputList(this, 16);
}
count = elements.length;
currentIdx = elements.length;
mask = elements.length - 1;
}
public CodecOutputList getOrCreate() {
if (count == 0) {
// Return a new CodecOutputList which will not be cached. We use a size of 4 to keep the overhead
// low.
return new CodecOutputList(NOOP_RECYCLER, 4);
}
--count;
int idx = (currentIdx - 1) & mask;
CodecOutputList list = elements[idx];
currentIdx = idx;
return list;
}
@Override
public void recycle(CodecOutputList codecOutputList) {
int idx = currentIdx;
elements[idx] = codecOutputList;
currentIdx = (idx + 1) & mask;
++count;
assert count <= elements.length;
}
}
static CodecOutputList newInstance() {
return CODEC_OUTPUT_LISTS_POOL.get().getOrCreate();
}
private final CodecOutputListRecycler recycler;
private int size;
private Object[] array;
private boolean insertSinceRecycled;
private CodecOutputList(CodecOutputListRecycler recycler, int size) {
this.recycler = recycler;
array = new Object[size];
}
@Override
public Object get(int index) {
checkIndex(index);
return array[index];
}
@Override
public int size() {
return size;
}
@Override
public boolean add(Object element) {
checkNotNull(element, "element");
try {
insert(size, element);
} catch (IndexOutOfBoundsException ignore) {
// This should happen very infrequently so we just catch the exception and try again.
expandArray();
insert(size, element);
}
++ size;
return true;
}
@Override
public Object set(int index, Object element) {
checkNotNull(element, "element");
checkIndex(index);
Object old = array[index];
insert(index, element);
return old;
}
@Override
public void add(int index, Object element) {
checkNotNull(element, "element");
checkIndex(index);
if (size == array.length) {
expandArray();
}
if (index != size) {
System.arraycopy(array, index, array, index + 1, size - index);
}
insert(index, element);
++ size;
}
@Override
public Object remove(int index) {
checkIndex(index);
Object old = array[index];
int len = size - index - 1;
if (len > 0) {
System.arraycopy(array, index + 1, array, index, len);
}
array[-- size] = null;
return old;
}
@Override
public void clear() {
// We only set the size to 0 and not null out the array. Null out the array will explicit requested by
// calling recycle()
size = 0;
}
/**
* Returns {@code true} if any elements where added or set. This will be reset once {@link #recycle()} was called.
*/
boolean insertSinceRecycled() {
return insertSinceRecycled;
}
/**
* Recycle the array which will clear it and null out all entries in the internal storage.
*/
void recycle() {
for (int i = 0 ; i < size; i ++) {
array[i] = null;
}
size = 0;
insertSinceRecycled = false;
recycler.recycle(this);
}
/**
* Returns the element on the given index. This operation will not do any range-checks and so is considered unsafe.
*/
Object getUnsafe(int index) {
return array[index];
}
private void checkIndex(int index) {
if (index >= size) {
throw new IndexOutOfBoundsException("expected: index < ("
+ size + "),but actual is (" + size + ")");
}
}
private void insert(int index, Object element) {
array[index] = element;
insertSinceRecycled = true;
}
private void expandArray() {
// double capacity
int newCapacity = array.length << 1;
if (newCapacity < 0) {
throw new OutOfMemoryError();
}
Object[] newArray = new Object[newCapacity];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
}