001/**
002 * Copyright (C) 2012 FuseSource, Inc.
003 * http://fusesource.com
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.fusesource.hawtdispatch.util;
018
019import java.util.ArrayList;
020
021/**
022 * <p>
023 * </p>
024 *
025 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
026 */
027abstract public class ThreadLocalPool<T> {
028
029    class Pool {
030        final ArrayList<T> objects = new ArrayList<T>(maxPoolSizePerThread());
031        long hitCounter;
032        long missCounter;
033//        public void monitor() {
034//            DispatchQueue current = Dispatch.getCurrentThreadQueue();
035//            if( current!=null ) {
036//                current.executeAfter(1, TimeUnit.SECONDS, new Task() {
037//                    @Override
038//                    public void run() {
039//                        if( hitCounter + missCounter > 0 ) {
040//                            System.out.println(String.format("Pool stats: %d hits, %d misses =  %f percent",
041//                                    hitCounter, missCounter, 100.0*hitCounter/(hitCounter + missCounter)));
042//                        }
043//                        hitCounter=0;
044//                        missCounter=0;
045//                        monitor();
046//                    }
047//                });
048//            }
049//        }
050    }
051
052    private final ThreadLocal<Pool> objectsThreadLocal = new ThreadLocal<Pool>();
053
054    abstract protected T create();
055
056    protected int maxPoolSizePerThread() {
057        return 10;
058    }
059
060    private Pool getPool() {
061        Pool rc = objectsThreadLocal.get();
062        if (rc == null) {
063            rc = new Pool();
064//            rc.monitor();
065            objectsThreadLocal.set(rc);
066        }
067        return rc;
068    }
069
070    public T checkout() {
071        Pool pool = getPool();
072        ArrayList<T> objects = pool.objects;
073        if (!objects.isEmpty()) {
074            pool.hitCounter++;
075            return objects.remove(objects.size() - 1);
076        } else {
077            pool.missCounter++;
078            return create();
079        }
080    }
081
082    public void checkin(T value) {
083        ArrayList<T> objects = getPool().objects;
084        if (objects.size() < maxPoolSizePerThread()) {
085            objects.add(value);
086        }
087    }
088
089
090}