All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.util.LockedPool Maven / Gradle / Ivy

The newest version!
//
// ========================================================================
// 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.Collectors;
import java.util.stream.Stream;

import org.eclipse.jetty.util.thread.AutoLock;

/**
 * 

A {@link Pool.Wrapper} that tracks the acquire/release/remove pool events.

*

The acquire/release/remove pool events are forwarded atomically to be handled * by a {@link Tracker} implementation, so that the pool event and the handling of * the event by the tracker are atomic.

* * @param

the type of the pooled objects */ public class LockedPool

extends Pool.Wrapper

{ private final AutoLock lock = new AutoLock(); private final Tracker

tracker; public LockedPool(Pool

pool) { this(pool, Tracker.noTracker()); } public LockedPool(Pool

pool, Tracker

tracker) { super(pool); this.tracker = tracker; } @Override public Entry

reserve() { try (AutoLock ignored = lock.lock()) { Entry

entry = super.reserve(); if (entry == null) return null; return new LockedEntry(entry); } } @Override public Entry

acquire() { try (AutoLock ignored = lock.lock()) { Entry

entry = super.acquire(); if (entry == null) return null; LockedEntry lockedEntry = new LockedEntry(entry); tracker.acquired(getWrapped(), entry); return lockedEntry; } } @Override public Entry

acquire(Function, P> creator) { try (AutoLock ignored = lock.lock()) { Entry

entry = super.acquire(creator); if (entry == null) return null; LockedEntry lockedEntry = new LockedEntry(entry); tracker.acquired(getWrapped(), entry); return lockedEntry; } } @Override public boolean isTerminated() { try (AutoLock ignored = lock.lock()) { return super.isTerminated(); } } @Override public Collection> terminate() { try (AutoLock ignored = lock.lock()) { Collection> result = super.terminate(); tracker.terminated(getWrapped(), result); return result.stream() .map(LockedEntry::new) .collect(Collectors.toList()); } } @Override public int size() { try (AutoLock ignored = lock.lock()) { return super.size(); } } @Override public int getMaxSize() { try (AutoLock ignored = lock.lock()) { return super.getMaxSize(); } } @Override public Stream> stream() { try (AutoLock ignored = lock.lock()) { return super.stream().map(LockedEntry::new); } } private class LockedEntry extends Entry.Wrapper

{ public LockedEntry(Entry

wrapped) { super(wrapped); } @Override public boolean release() { try (AutoLock ignored = lock.lock()) { boolean released = super.release(); if (released) tracker.released(LockedPool.this.getWrapped(), getWrapped()); return released; } } @Override public boolean remove() { try (AutoLock ignored = lock.lock()) { boolean removed = super.remove(); if (removed) tracker.removed(LockedPool.this.getWrapped(), getWrapped()); return removed; } } } /** *

A {@link Pool.Factory} that wraps newly created * {@link Pool} instances with {@link LockedPool}.

* * @param the type of pooled objects */ public interface Factory extends Pool.Factory { @Override public default Pool wrap(Pool pool) { return new LockedPool<>(pool); } } /** *

A receiver of {@link Pool} events.

*

A simple implementations may just count acquire/release/remove * pool events via, respectively, {@link #acquired(Pool, Entry)}, * {@link #released(Pool, Entry)} and {@link #removed(Pool, Entry)}, * and make sure that the count is {@code 0} when * {@link #terminated(Pool, Collection)} is called.

*

More advanced implementations may also obtain a stack trace at * the time of the event to troubleshoot leaking of pooled entries.

* * @param the type of pooled objects */ public interface Tracker { /** * @return a no-op implementation of {@code Tracker} * @param the type of pooled objects */ @SuppressWarnings("unchecked") public static Tracker noTracker() { class NoTracker implements Tracker { private static final Tracker INSTANCE = new NoTracker(); } return (Tracker)NoTracker.INSTANCE; } /** *

Callback method invoked when an entry is * {@link Pool#acquire() acquired}.

* * @param pool the pool * @param entry the acquired entry */ public default void acquired(Pool pool, Entry entry) { } /** *

Callback method invoked when an entry is * {@link Entry#release() released}.

* * @param pool the pool * @param entry the released entry */ public default void released(Pool pool, Entry entry) { } /** *

Callback method invoked when an entry is * {@link Entry#remove() removed}.

* * @param pool the pool * @param entry the removed entry */ public default void removed(Pool pool, Entry entry) { } /** *

Callback method invoked when the {@code Pool} * is {@link Pool#terminate() terminated}.

* * @param pool the pool * @param entries the list of entries at termination */ public default void terminated(Pool pool, Collection> entries) { } } }