org.elasticsearch.common.recycler.Recyclers Maven / Gradle / Ivy
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.common.recycler;
import com.carrotsearch.hppc.BitMixer;
import java.util.ArrayDeque;
public enum Recyclers {
;
/**
* Return a {@link Recycler} that never recycles entries.
*/
public static Recycler none(Recycler.C c) {
return new NoneRecycler<>(c);
}
/**
* Return a concurrent recycler based on a deque.
*/
public static Recycler concurrentDeque(Recycler.C c, int limit) {
return new ConcurrentDequeRecycler<>(c, limit);
}
/**
* Return a recycler based on a deque.
*/
public static Recycler deque(Recycler.C c, int limit) {
return new DequeRecycler<>(c, new ArrayDeque<>(), limit);
}
/**
* Return a recycler based on a deque.
*/
public static Recycler.Factory dequeFactory(final Recycler.C c, final int limit) {
return () -> deque(c, limit);
}
/**
* Wrap the provided recycler so that calls to {@link Recycler#obtain()} and {@link Recycler.V#close()} are protected by
* a lock.
*/
public static Recycler locked(final Recycler recycler) {
return new FilterRecycler() {
private final Object lock;
{
this.lock = new Object();
}
@Override
protected Recycler getDelegate() {
return recycler;
}
@Override
public Recycler.V obtain() {
synchronized (lock) {
return super.obtain();
}
}
@Override
protected Recycler.V wrap(final Recycler.V delegate) {
return new Recycler.V() {
@Override
public void close() {
synchronized (lock) {
delegate.close();
}
}
@Override
public T v() {
return delegate.v();
}
@Override
public boolean isRecycled() {
return delegate.isRecycled();
}
};
}
};
}
/**
* Create a concurrent implementation that can support concurrent access from
* concurrencyLevel
threads with little contention.
*/
public static Recycler concurrent(final Recycler.Factory factory, final int concurrencyLevel) {
if (concurrencyLevel < 1) {
throw new IllegalArgumentException("concurrencyLevel must be >= 1");
}
if (concurrencyLevel == 1) {
return locked(factory.build());
}
return new FilterRecycler() {
private final Recycler[] recyclers;
{
@SuppressWarnings({ "rawtypes", "unchecked" })
final Recycler[] recyclers = new Recycler[concurrencyLevel];
this.recyclers = recyclers;
for (int i = 0; i < concurrencyLevel; ++i) {
recyclers[i] = locked(factory.build());
}
}
int slot() {
final long id = Thread.currentThread().getId();
// don't trust Thread.hashCode to have equiprobable low bits
int slot = (int) BitMixer.mix64(id);
// make positive, otherwise % may return negative numbers
slot &= 0x7FFFFFFF;
slot %= concurrencyLevel;
return slot;
}
@Override
protected Recycler getDelegate() {
return recyclers[slot()];
}
};
}
public static Recycler concurrent(final Recycler.Factory factory) {
return concurrent(factory, Runtime.getRuntime().availableProcessors());
}
}