org.eclipse.jetty.util.Pool Maven / Gradle / Ivy
Show all versions of jetty-util Show documentation
//
// ========================================================================
// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License v. 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
//
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
// ========================================================================
//
package org.eclipse.jetty.util;
import java.util.Collection;
import java.util.function.Function;
import java.util.stream.Stream;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
/**
* A pool of objects, with support for multiplexing and several
* optimized strategies plus an optional {@link ThreadLocal} cache
* of the last released entry.
* A {@code Pool} should be {@link #terminate() terminated} when
* it is no longer needed; once terminated, it cannot be used anymore.
*
* @param the type of the pooled objects
*/
@ManagedObject
public interface Pool
{
/**
*
Creates a new disabled slot into the pool.
* The returned entry must ultimately have the {@link Entry#enable(Object, boolean)}
* method called or be removed via {@link Pool.Entry#remove()}.
*
* @return a disabled entry that is contained in the pool, or {@code null}
* if the pool is terminated or if the pool cannot reserve an entry
*/
Entry reserve();
/**
*
Acquires an entry from the pool.
* Only enabled entries will be returned from this method
* and their {@link Entry#enable(Object, boolean)}
* method must not be called.
*
* @return an entry from the pool or null if none is available.
*/
Entry acquire();
/**
*
Acquires an entry from the pool,
* reserving and creating a new entry if necessary.
*
* @param creator a function to create the pooled value for a reserved entry.
* @return an entry from the pool or null if none is available.
*/
default Entry acquire(Function, P> creator)
{
Entry entry = acquire();
if (entry != null)
return entry;
entry = reserve();
if (entry == null)
return null;
P value;
try
{
value = creator.apply(entry);
}
catch (Throwable th)
{
entry.remove();
throw th;
}
if (value == null)
{
entry.remove();
return null;
}
return entry.enable(value, true) ? entry : null;
}
/**
* @return whether this {@code Pool} has been terminated
* @see #terminate()
*/
boolean isTerminated();
/**
*
Terminates this {@code Pool}.
* All the entries are marked as terminated and cannot be
* acquired nor released, but only removed.
* The returned list of all entries may be iterated to
* perform additional operations on the pooled objects.
* The pool cannot be used anymore after it is terminated.
*
* @return a list of all entries
*/
Collection> terminate();
/**
* @return the current number of entries in this {@code Pool}
*/
@ManagedAttribute("The number of entries")
int size();
/**
* @return the maximum number of entries in this {@code Pool}
*/
@ManagedAttribute("The maximum number of entries")
int getMaxSize();
/**
* @return a {@link Stream} over the entries
*/
Stream> stream();
/**
* @return the number of reserved entries
*/
@ManagedAttribute("The number of reserved entries")
default int getReservedCount()
{
return (int)stream().filter(Entry::isReserved).count();
}
/**
* @return the number of idle entries
*/
@ManagedAttribute("The number of idle entries")
default int getIdleCount()
{
return (int)stream().filter(Entry::isIdle).count();
}
/**
* @return the number of in-use entries
*/
@ManagedAttribute("The number of in-use entries")
default int getInUseCount()
{
return (int)stream().filter(Entry::isInUse).count();
}
/**
* @return the number of terminated entries
*/
@ManagedAttribute("The number of terminated entries")
default int getTerminatedCount()
{
return (int)stream().filter(Entry::isTerminated).count();
}
/**
* A wrapper for {@code Pool} instances.
*
* @param the type of the pooled objects
*/
class Wrapper implements Pool
{
private final Pool wrapped;
public Wrapper(Pool wrapped)
{
this.wrapped = wrapped;
}
public Pool getWrapped()
{
return wrapped;
}
@Override
public Entry reserve()
{
return getWrapped().reserve();
}
@Override
public Entry acquire()
{
return getWrapped().acquire();
}
@Override
public Entry acquire(Function, W> creator)
{
return getWrapped().acquire(creator);
}
@Override
public boolean isTerminated()
{
return getWrapped().isTerminated();
}
@Override
public Collection> terminate()
{
return getWrapped().terminate();
}
@Override
public int size()
{
return getWrapped().size();
}
@Override
public int getMaxSize()
{
return getWrapped().getMaxSize();
}
@Override
public Stream> stream()
{
return getWrapped().stream();
}
@Override
public int getReservedCount()
{
return getWrapped().getReservedCount();
}
@Override
public int getIdleCount()
{
return getWrapped().getIdleCount();
}
@Override
public int getInUseCount()
{
return getWrapped().getInUseCount();
}
@Override
public int getTerminatedCount()
{
return getWrapped().getTerminatedCount();
}
}
/**
* A {@code Pool} entry that holds metadata and a pooled object.
*
* @param the type of the pooled objects
*/
interface Entry
{
/**
* Enables this, previously {@link #reserve() reserved}, {@code Entry}.
* An entry returned from the {@link #reserve()} method must be enabled
* with this method, once and only once, before it is usable by the pool.
* The entry may be enabled and not acquired, in which case it is immediately
* available to be acquired, potentially by another thread; or it can be enabled
* and acquired atomically so that no other thread can acquire it, although the
* acquire may still fail if the pool has been terminated.
*
* @param pooled the pooled object for this {@code Entry}
* @param acquire whether this {@code Entry} should be atomically enabled and acquired
* @return whether this {@code Entry} was enabled
* @throws IllegalStateException if this {@code Entry} was already enabled
*/
boolean enable(E pooled, boolean acquire);
/**
* @return the pooled object
*/
E getPooled();
/**
* Releases this {@code Entry} to the {@code Pool}.
*
* @return whether this {@code Entry} was released
*/
boolean release();
/**
* Removes this {@code Entry} from the {@code Pool}.
*
* @return whether this {@code Entry} was removed
*/
boolean remove();
/**
* @return whether this {@code Entry} is reserved
* @see Pool#reserve()
*/
boolean isReserved();
/**
* @return whether this {@code Entry} is idle in the {@code Pool}
*/
boolean isIdle();
/**
* @return whether this {@code Entry} is in use
*/
boolean isInUse();
/**
* @return whether this {@code Entry} is terminated
*/
boolean isTerminated();
/**
* A wrapper for {@code Entry} instances.
*
* @param the type of the pooled objects
*/
class Wrapper implements Entry
{
private final Entry wrapped;
public Wrapper(Entry wrapped)
{
this.wrapped = wrapped;
}
public Entry getWrapped()
{
return wrapped;
}
@Override
public boolean enable(W pooled, boolean acquire)
{
return getWrapped().enable(pooled, acquire);
}
@Override
public W getPooled()
{
return getWrapped().getPooled();
}
@Override
public boolean release()
{
return getWrapped().release();
}
@Override
public boolean remove()
{
return getWrapped().remove();
}
@Override
public boolean isReserved()
{
return getWrapped().isReserved();
}
@Override
public boolean isIdle()
{
return getWrapped().isIdle();
}
@Override
public boolean isInUse()
{
return getWrapped().isInUse();
}
@Override
public boolean isTerminated()
{
return getWrapped().isTerminated();
}
}
}
/**
* A factory for {@link Pool} instances.
*
* @param the type of the pooled objects
*/
interface Factory
{
/**
* @return a new {@link Pool} instance
*/
public Pool newPool();
/**
* Wraps, if necessary, the given pool.
*
* @param pool the pool to wrap
* @return a possibly wrapped pool
* @see Pool.Wrapper
*/
public default Pool wrap(Pool pool)
{
return pool;
}
}
}