/* * from: http://ashkrit.blogspot.com/2013/05/lock-less-java-object-pool.html * https://github.com/ashkrit/blog/tree/master/FastObjectPool * copyright ashkrit 2013 * * 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.security.AccessController; import java.util.concurrent.locks.ReentrantLock; class UnsafeObjectPool implements ObjectPool { private final sun.misc.Unsafe unsafe; private static final boolean FREE = true; private static final boolean USED = false; private final ObjectPoolHolder[] objects; private volatile int takePointer; private volatile int releasePointer; private final int mask; private final long BASE; private final long INDEXSCALE; private final long ASHIFT; public ReentrantLock lock = new ReentrantLock(); private ThreadLocal> localValue = new ThreadLocal<>(); UnsafeObjectPool(PoolableObject poolableObject, int size) throws Throwable { this.unsafe = AccessController.doPrivileged(new GetUnsafe()); if (this.unsafe == null) { throw new Exception("Unable to load unsafe"); } int newSize = 1; while (newSize < size) { newSize = newSize << 1; } size = newSize; @SuppressWarnings({"unchecked", "rawtypes"}) ObjectPoolHolder[] stuff = new ObjectPoolHolder[size]; this.objects = stuff; for (int x=0;x(poolableObject.create()); } this.mask = size-1; this.releasePointer = size; this.BASE = this.unsafe.arrayBaseOffset(ObjectPoolHolder[].class); this.INDEXSCALE = this.unsafe.arrayIndexScale(ObjectPoolHolder[].class); this.ASHIFT = 31 - Integer.numberOfLeadingZeros((int) this.INDEXSCALE); } @Override public ObjectPoolHolder take() { int localTakePointer; // 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; } } sun.misc.Unsafe unsafe = this.unsafe; while (this.releasePointer != (localTakePointer=this.takePointer)) { int index = localTakePointer & this.mask; ObjectPoolHolder holder = this.objects[index]; //if(holder!=null && THE_UNSAFE.compareAndSwapObject(objects, (index*INDEXSCALE)+BASE, holder, null)) if (holder != null && unsafe.compareAndSwapObject(this.objects, (index< object) { try { this.lock.lockInterruptibly(); int localValue = this.releasePointer; //long index = ((localValue & mask) * INDEXSCALE ) + BASE; long index = ((localValue & this.mask)<