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     */
017    package org.fusesource.hawtdispatch.util;
018    
019    import java.util.ArrayList;
020    
021    /**
022     * <p>
023     * </p>
024     *
025     * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
026     */
027    abstract 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    }