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

com.epam.deltix.qsrv.hf.blocks.ObjectPool Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2023 EPAM Systems, Inc
 *
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership. Licensed 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 com.epam.deltix.qsrv.hf.blocks;

import java.util.ArrayList;

import net.jcip.annotations.GuardedBy;

/**
 * Object pool. Thread-safe with exception of unit-test-only methods marked otherwise.
 * @author Andy
 *         Date: Sep 22, 2009 10:29:44 PM
 */
public abstract class ObjectPool {
    // buffer will shrink by half of extra space
    static final int SHRINK_FACTOR = 2;
    static final int TRIM_FACTOR = 2;

    @GuardedBy("pool")
    private final ArrayList pool;
    @GuardedBy("pool")
    private int minSize;
    @GuardedBy("pool")
    private int maxSize;

    private final int limit;

    public ObjectPool(int initialCapacity) {
        this(initialCapacity, Integer.MAX_VALUE);
    }

    public ObjectPool(int initialCapacity, int limitCapacity) {
        pool = new ArrayList(initialCapacity);
        for (int i = 0; i < initialCapacity; i++)
            pool.add (newItem());
        minSize = maxSize = initialCapacity;

        limit = limitCapacity;
    }

    public final T borrow () {
        synchronized (pool) {
            int size = pool.size();
            if (size == 0) {
                minSize = 0;
                maxSize ++; // lets account for future release (maxSize is only used to avoid trimToSize())
                return newItem();
            } else {
                size--;
                if (size < minSize)
                    minSize = size;
                return pool.remove(size);
            }
        }
    }

    protected abstract T newItem();

    public final boolean release(T msg) {

        if (msg != null) {
            synchronized (pool) {
                int size = pool.size();

                boolean add = size < limit;
                if (add) {
                    pool.add(msg);
                    size++;
                }

                if (size > maxSize)
                    maxSize = size;

                return add;
            }
        }

        return false;
    }


    public final void trim() {
        synchronized (pool) {
            if (minSize > 0) {
                final int size = pool.size();

                // buffer has at least minSize elements that were not used since last trim()
                final int shrinkSize = (size - minSize / SHRINK_FACTOR);

                // yet up to (maxSize - size) may be released soon, so better keep ArrayList capacity
                if (maxSize / size > TRIM_FACTOR) {
                    pool.trimToSize();
                    maxSize = shrinkSize;
                }

                for (int i = size - 1; i >= shrinkSize; i--)
                    pool.remove(i);

                minSize = shrinkSize; // reset
            }
        }
    }

    /** NO SYNCHRONIZATION: TEST ONLY */
    int size() {
        return pool.size();
    }

    int minSize() {
        return minSize;
    }

    int maxSize() {
        return maxSize;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy