| /* | |
| * Copyright (c) 2016, 2022, 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<>(ctx); | |
| break; | |
| case REF_SOFT: | |
| ctx.reference = new SoftReference<>(ctx); | |
| break; | |
| default: | |
| case REF_WEAK: | |
| ctx.reference = new WeakReference<>(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; | |
| } | |
| } | |
| } |