/* * from: https://code.google.com/p/furious-objectpool/ * copyright Eddie Raapoto 2012 * * 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. * * Modified by dorkbox, llc */ package dorkbox.objectPool; import java.util.concurrent.LinkedBlockingDeque; class SafeObjectPool implements ObjectPool { private static final boolean FREE = true; private static final boolean USED = false; private final LinkedBlockingDeque> queue; private ThreadLocal> localValue = new ThreadLocal<>(); SafeObjectPool(PoolableObject poolableObject, int size) { this.queue = new LinkedBlockingDeque>(size); for (int x=0;x(poolableObject.create())); } } @Override public ObjectPoolHolder take() { // if we have an object available in the cache, use it instead. ObjectPoolHolder localObject = this.localValue.get(); if (localObject != null) { if (localObject.state.compareAndSet(FREE, USED)) { return localObject; } } ObjectPoolHolder holder = this.queue.poll(); if (holder == null) { return null; } // the use of a threadlocal reference here helps eliminates contention. This also checks OTHER threads, // as they might have one sitting on the cache if (holder.state.compareAndSet(FREE, USED)) { this.localValue.set(holder); return holder; } else { // put it back into the queue this.queue.offer(holder); return null; } } @Override public void release(ObjectPoolHolder object) { if (object.state.compareAndSet(USED, FREE)) { this.queue.offer(object); } else { throw new IllegalArgumentException("Invalid reference passed"); } } }