| /* | |
| * 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; | |
| /** | |
| * This ReentrantContextProvider implementation uses a ThreadLocal to hold | |
| * the first ReentrantContext per thread and a ReentrantContextProviderCLQ to | |
| * store child ReentrantContext instances needed during recursion. | |
| * | |
| * Note: this implementation may keep up to one context in memory per thread. | |
| * Child contexts for recursive uses are stored in the queue using a WEAK | |
| * reference by default unless specified in the 2 argument constructor. | |
| * | |
| * @param <K> ReentrantContext subclass | |
| */ | |
| public abstract class ReentrantContextProviderTL<K extends ReentrantContext> | |
| extends ReentrantContextProvider<K> | |
| { | |
| // Thread-local storage: | |
| private final ThreadLocal<Reference<K>> ctxTL | |
| = new ThreadLocal<>(); | |
| // ReentrantContext CLQ provider for child contexts: | |
| private final ReentrantContextProviderCLQ<K> ctxProviderCLQ; | |
| /** | |
| * Create a new ReentrantContext provider using the given reference type | |
| * among hard, soft or weak. | |
| * It uses weak reference for the child contexts. | |
| * | |
| * @param refType reference type | |
| */ | |
| public ReentrantContextProviderTL(final int refType) { | |
| this(refType, REF_WEAK); | |
| } | |
| /** | |
| * Create a new ReentrantContext provider using the given reference types | |
| * among hard, soft or weak | |
| * | |
| * @param refTypeTL reference type used by ThreadLocal | |
| * @param refTypeCLQ reference type used by ReentrantContextProviderCLQ | |
| */ | |
| public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ) | |
| { | |
| super(refTypeTL); | |
| final ReentrantContextProviderTL<K> parent = this; | |
| this.ctxProviderCLQ = new ReentrantContextProviderCLQ<>(refTypeCLQ) { | |
| @Override | |
| protected K newContext() { | |
| return parent.newContext(); | |
| } | |
| }; | |
| } | |
| /** | |
| * Give a ReentrantContext instance for the current thread | |
| * | |
| * @return ReentrantContext instance | |
| */ | |
| @Override | |
| public final K acquire() { | |
| K ctx = null; | |
| final Reference<K> ref = ctxTL.get(); | |
| if (ref != null) { | |
| ctx = ref.get(); | |
| } | |
| if (ctx == null) { | |
| // create a new ReentrantContext if none is available | |
| ctx = newContext(); | |
| // update thread local reference: | |
| ctxTL.set(getOrCreateReference(ctx)); | |
| } | |
| // Check reentrance: | |
| if (ctx.usage == USAGE_TL_INACTIVE) { | |
| ctx.usage = USAGE_TL_IN_USE; | |
| } else { | |
| // get or create another ReentrantContext from CLQ provider: | |
| ctx = ctxProviderCLQ.acquire(); | |
| } | |
| return ctx; | |
| } | |
| /** | |
| * Restore the given ReentrantContext instance for reuse | |
| * | |
| * @param ctx ReentrantContext instance | |
| */ | |
| @Override | |
| public final void release(final K ctx) { | |
| if (ctx.usage == USAGE_TL_IN_USE) { | |
| ctx.usage = USAGE_TL_INACTIVE; | |
| } else { | |
| ctxProviderCLQ.release(ctx); | |
| } | |
| } | |
| } |