124 lines
4.2 KiB
Java
124 lines
4.2 KiB
Java
/*
|
|
* 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;
|
|
|
|
/**
|
|
* 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<Reference<K>>();
|
|
|
|
// 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<K>(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);
|
|
}
|
|
}
|
|
}
|