Path: blob/master/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java
41152 views
/*1* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package sun.java2d;2526import java.lang.ref.Reference;2728/**29* This ReentrantContextProvider implementation uses a ThreadLocal to hold30* the first ReentrantContext per thread and a ReentrantContextProviderCLQ to31* store child ReentrantContext instances needed during recursion.32*33* Note: this implementation may keep up to one context in memory per thread.34* Child contexts for recursive uses are stored in the queue using a WEAK35* reference by default unless specified in the 2 argument constructor.36*37* @param <K> ReentrantContext subclass38*/39public abstract class ReentrantContextProviderTL<K extends ReentrantContext>40extends ReentrantContextProvider<K>41{42// Thread-local storage:43private final ThreadLocal<Reference<K>> ctxTL44= new ThreadLocal<Reference<K>>();4546// ReentrantContext CLQ provider for child contexts:47private final ReentrantContextProviderCLQ<K> ctxProviderCLQ;4849/**50* Create a new ReentrantContext provider using the given reference type51* among hard, soft or weak.52* It uses weak reference for the child contexts.53*54* @param refType reference type55*/56public ReentrantContextProviderTL(final int refType) {57this(refType, REF_WEAK);58}5960/**61* Create a new ReentrantContext provider using the given reference types62* among hard, soft or weak63*64* @param refTypeTL reference type used by ThreadLocal65* @param refTypeCLQ reference type used by ReentrantContextProviderCLQ66*/67public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ)68{69super(refTypeTL);7071final ReentrantContextProviderTL<K> parent = this;7273this.ctxProviderCLQ = new ReentrantContextProviderCLQ<K>(refTypeCLQ) {74@Override75protected K newContext() {76return parent.newContext();77}78};79}8081/**82* Give a ReentrantContext instance for the current thread83*84* @return ReentrantContext instance85*/86@Override87public final K acquire() {88K ctx = null;89final Reference<K> ref = ctxTL.get();90if (ref != null) {91ctx = ref.get();92}93if (ctx == null) {94// create a new ReentrantContext if none is available95ctx = newContext();96// update thread local reference:97ctxTL.set(getOrCreateReference(ctx));98}99// Check reentrance:100if (ctx.usage == USAGE_TL_INACTIVE) {101ctx.usage = USAGE_TL_IN_USE;102} else {103// get or create another ReentrantContext from CLQ provider:104ctx = ctxProviderCLQ.acquire();105}106return ctx;107}108109/**110* Restore the given ReentrantContext instance for reuse111*112* @param ctx ReentrantContext instance113*/114@Override115public final void release(final K ctx) {116if (ctx.usage == USAGE_TL_IN_USE) {117ctx.usage = USAGE_TL_INACTIVE;118} else {119ctxProviderCLQ.release(ctx);120}121}122}123124125