/
githubmirror
/
jdk22
Обзор
Документация
Войти
/
githubmirror
/
jdk22
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/java.base/share/classes/jdk/internal/vm/StackableScope.java
261 строка
8 KB
Alan Bateman
8284161: Implementation of Virtual Threads (Preview)
07 май 2022, 11:06
07 май 2022, 11:06
9583e36
Код
Авторство
О чём код?
/* * Copyright (c) 2021, 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 jdk.internal.vm; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.vm.annotation.DontInline; import jdk.internal.vm.annotation.ReservedStackAccess; /** * A stackable scope to support structured constructs. The push method is used to * push a StackableScope to the current thread's scope stack. The tryPop and * popForcefully methods are used to pop the StackableScope from the current thread's * scope stack. */ public class StackableScope { private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); private final Thread owner; private volatile StackableScope previous; /** * Creates a stackable scope. * @param shared true for a shared scope that cannot be pushed to the stack, * false for scope that is owned by the current thread */ StackableScope(boolean shared) { if (shared) { this.owner = null; } else { this.owner = Thread.currentThread(); } } /** * Creates a stackable scope owned by the current thread. */ protected StackableScope() { this(false); } /** * Returns the scope owner or null if not owned. */ public Thread owner() { return owner; } /** * Pushes this scope onto the current thread's scope stack. * @throws WrongThreadException it the current thread is not the owner */ public StackableScope push() { if (Thread.currentThread() != owner) throw new WrongThreadException("Not owner"); previous = head(); setHead(this); return this; } /** * Pops this scope from the current thread's scope stack if the scope is * at the top of stack. * @return true if the pop succeeded, false if this scope is not the top of stack * @throws WrongThreadException it the current thread is not the owner */ @DontInline @ReservedStackAccess public boolean tryPop() { if (Thread.currentThread() != owner) throw new WrongThreadException("Not owner"); if (head() == this) { setHead(previous); previous = null; return true; } else { return false; } } /** * Pops this scope from the current thread's scope stack. * * For well-behaved usages, this scope is at the top of the stack. It is popped * from the stack and the method returns {@code true}. * * If this scope is not at the top of the stack then this method attempts to * close each of the intermediate scopes by invoking their {@link #tryClose()} * method. If tryClose succeeds then the scope is removed from the stack. When * done, this scope is removed from the stack and {@code false} is returned. * * This method does nothing, and returns {@code false}, if this scope is not * on the current thread's scope stack. * * @return true if this scope was at the top of the stack, otherwise false * @throws WrongThreadException it the current thread is not the owner */ @DontInline @ReservedStackAccess public boolean popForcefully() { if (Thread.currentThread() != owner) throw new WrongThreadException("Not owner"); final StackableScope head = head(); if (head == this) { setHead(previous); previous = null; return true; } // scope is not the top of stack if (contains(this)) { StackableScope current = head; while (current != this) { StackableScope previous = current.previous(); // attempt to forcefully close the scope and remove from stack if (current.tryClose()) { current.unlink(); } current = previous; } unlink(); } return false; } /** * Pops all scopes from the current thread's scope stack. */ public static void popAll() { StackableScope head = head(); if (head != null) { StackableScope current = head; while (current != null) { assert Thread.currentThread() == current.owner(); current.tryClose(); current = current.previous(); } setHead(null); } } /** * Returns the scope that encloses this scope. */ public StackableScope enclosingScope() { StackableScope previous = this.previous; if (previous != null) return previous; if (owner != null) return JLA.threadContainer(owner); return null; } /** * Returns the scope of the given type that encloses this scope. */ public <T extends StackableScope> T enclosingScope(Class<T> type) { StackableScope current = enclosingScope(); while (current != null) { if (type.isInstance(current)) { @SuppressWarnings("unchecked") T tmp = (T) current; return tmp; } current = current.enclosingScope(); } return null; } /** * Returns the scope that directly encloses this scope, null if none. */ StackableScope previous() { return previous; } /** * Returns the scope that this scope directly encloses, null if none. */ private StackableScope next() { assert contains(this); StackableScope current = head(); StackableScope next = null; while (current != this) { next = current; current = current.previous(); } return next; } /** * Override this method to close this scope and release its resources. * This method should not pop the scope from the stack. * This method is guaranteed to execute on the owner thread. * @return true if this method closed the scope, false if it failed */ protected boolean tryClose() { assert Thread.currentThread() == owner; return false; } /** * Removes this scope from the current thread's scope stack. */ private void unlink() { assert contains(this); StackableScope next = next(); if (next == null) { setHead(previous); } else { next.previous = previous; } previous = null; } /** * Returns true if the given scope is on the current thread's scope stack. */ private static boolean contains(StackableScope scope) { assert scope != null; StackableScope current = head(); while (current != null && current != scope) { current = current.previous(); } return (current == scope); } /** * Returns the head of the current thread's scope stack. */ static StackableScope head() { return JLA.headStackableScope(Thread.currentThread()); } /** * Sets the head (top) of the current thread's scope stack. */ private static void setHead(StackableScope scope) { JLA.setHeadStackableScope(scope); } }