blob: 92132aabcc455b3d2eef2a5083fac3f7ee5aaeef [file] [log] [blame]
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* This abstract ReentrantContextProvider helper class manages the creation,
* storage, and retrieval of concrete ReentrantContext instances which can be
* subclassed to hold cached contextual data.
*
* It supports reentrancy as every call to acquire() provides a new unique context
* instance that must later be returned for reuse by a call to release(ctx)
* (typically in a try/finally block).
*
* It has a couple of abstract implementations which store references in a queue
* and/or thread-local storage.
* The Providers can be configured to hold ReentrantContext instances in memory
* using hard, soft or weak references.
*
* The acquire() and release() methods are used to retrieve and return the contexts.
*
* The {@code newContext()} method remains abstract in all implementations and
* must be provided by the module to create a new subclass of ReentrantContext
* with the appropriate contextual data in it.
*
* Sample Usage:
* - create a subclass ReentrantContextImpl to hold the thread state:
*
* static final class ReentrantContextImpl extends ReentrantContext {
* // specific cached data
* }
*
* - create the appropriate ReentrantContextProvider:
*
* private static final ReentrantContextProvider<ReentrantContextImpl> contextProvider =
* new ReentrantContextProviderTL<ReentrantContextImpl>(ReentrantContextProvider.REF_WEAK)
* {
* @Override
* protected ReentrantContextImpl newContext() {
* return new ReentrantContextImpl();
* }
* };
* ...
* void someMethod() {
* ReentrantContextImpl ctx = contextProvider.acquire();
* try {
* // use the context
* } finally {
* contextProvider.release(ctx);
* }
* }
*
* @param <K> ReentrantContext subclass
*
* @see ReentrantContext
*/
public abstract class ReentrantContextProvider<K extends ReentrantContext>
{
// thread-local storage: inactive
static final byte USAGE_TL_INACTIVE = 0;
// thread-local storage: in use
static final byte USAGE_TL_IN_USE = 1;
// CLQ storage
static final byte USAGE_CLQ = 2;
// hard reference
public static final int REF_HARD = 0;
// soft reference
public static final int REF_SOFT = 1;
// weak reference
public static final int REF_WEAK = 2;
/* members */
// internal reference type
private final int refType;
/**
* Create a new ReentrantContext provider using the given reference type
* among hard, soft or weak
*
* @param refType reference type
*/
protected ReentrantContextProvider(final int refType) {
this.refType = refType;
}
/**
* Create a new ReentrantContext instance
*
* @return new ReentrantContext instance
*/
protected abstract K newContext();
/**
* Give a ReentrantContext instance for the current thread
*
* @return ReentrantContext instance
*/
public abstract K acquire();
/**
* Restore the given ReentrantContext instance for reuse
*
* @param ctx ReentrantContext instance
*/
public abstract void release(K ctx);
@SuppressWarnings("unchecked")
protected final Reference<K> getOrCreateReference(final K ctx) {
if (ctx.reference == null) {
// Create the reference:
switch (refType) {
case REF_HARD:
ctx.reference = new HardReference<K>(ctx);
break;
case REF_SOFT:
ctx.reference = new SoftReference<K>(ctx);
break;
default:
case REF_WEAK:
ctx.reference = new WeakReference<K>(ctx);
break;
}
}
return (Reference<K>) ctx.reference;
}
/* Missing HardReference implementation */
static final class HardReference<V> extends WeakReference<V> {
// kept strong reference:
private final V strongRef;
HardReference(final V referent) {
// no referent needed for the parent WeakReference:
super(null);
this.strongRef = referent;
}
@Override
public V get() {
return strongRef;
}
}
}