org.elasticsearch.common.recycler.Recyclers Maven / Gradle / Ivy
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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
*
* 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.
*/
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 new Recycler.Factory() {
@Override
public Recycler build() {
return deque(c, limit);
}
};
}
/**
* Wrap two recyclers and forward to calls to smallObjectRecycler
when size < minSize
and to
* defaultRecycler
otherwise.
*/
public static Recycler sizing(final Recycler defaultRecycler, final Recycler smallObjectRecycler, final int minSize) {
return new FilterRecycler() {
@Override
protected Recycler getDelegate() {
return defaultRecycler;
}
@Override
public Recycler.V obtain(int sizing) {
if (sizing > 0 && sizing < minSize) {
return smallObjectRecycler.obtain(sizing);
}
return super.obtain(sizing);
}
@Override
public void close() {
defaultRecycler.close();
smallObjectRecycler.close();
}
};
}
/**
* 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 org.elasticsearch.common.recycler.Recycler.V obtain(int sizing) {
synchronized (lock) {
return super.obtain(sizing);
}
}
@Override
public org.elasticsearch.common.recycler.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("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()];
}
@Override
public void close() {
for (Recycler recycler : recyclers) {
recycler.close();
}
}
};
}
public static Recycler concurrent(final Recycler.Factory factory) {
return concurrent(factory, Runtime.getRuntime().availableProcessors());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy