8284161: Implementation of Virtual Threads (Preview)

Co-authored-by: Ron Pressler <rpressler@openjdk.org>
Co-authored-by: Alan Bateman <alanb@openjdk.org>
Co-authored-by: Erik Österlund <eosterlund@openjdk.org>
Co-authored-by: Andrew Haley <aph@openjdk.org>
Co-authored-by: Rickard Bäckman <rbackman@openjdk.org>
Co-authored-by: Markus Grönlund <mgronlun@openjdk.org>
Co-authored-by: Leonid Mesnik <lmesnik@openjdk.org>
Co-authored-by: Serguei Spitsyn <sspitsyn@openjdk.org>
Co-authored-by: Chris Plummer <cjplummer@openjdk.org>
Co-authored-by: Coleen Phillimore <coleenp@openjdk.org>
Co-authored-by: Robbin Ehn <rehn@openjdk.org>
Co-authored-by: Stefan Karlsson <stefank@openjdk.org>
Co-authored-by: Thomas Schatzl <tschatzl@openjdk.org>
Co-authored-by: Sergey Kuksenko <skuksenko@openjdk.org>
Reviewed-by: lancea, eosterlund, rehn, sspitsyn, stefank, tschatzl, dfuchs, lmesnik, dcubed, kevinw, amenkov, dlong, mchung, psandoz, bpb, coleenp, smarks, egahlin, mseledtsov, coffeys, darcy
This commit is contained in:
Alan Bateman 2022-05-07 08:06:16 +00:00
parent 5212535a27
commit 9583e3657e
1133 changed files with 95935 additions and 8335 deletions

View file

@ -24,12 +24,12 @@
*/
package java.lang;
import jdk.internal.misc.TerminatingThreadLocal;
import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import jdk.internal.misc.TerminatingThreadLocal;
/**
* This class provides thread-local variables. These variables differ from
@ -156,21 +156,40 @@ public class ThreadLocal<T> {
* thread-local variable. If the variable has no value for the
* current thread, it is first initialized to the value returned
* by an invocation of the {@link #initialValue} method.
* If the current thread does not support thread locals then
* this method returns its {@link #initialValue} (or {@code null}
* if the {@code initialValue} method is not overridden).
*
* @return the current thread's value of this thread-local
* @see Thread.Builder#allowSetThreadLocals(boolean)
*/
public T get() {
Thread t = Thread.currentThread();
return get(Thread.currentThread());
}
/**
* Returns the value in the current carrier thread's copy of this
* thread-local variable.
*/
T getCarrierThreadLocal() {
return get(Thread.currentCarrierThread());
}
private T get(Thread t) {
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
if (map == ThreadLocalMap.NOT_SUPPORTED) {
return initialValue();
} else {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T) e.value;
return result;
}
}
}
return setInitialValue();
return setInitialValue(t);
}
/**
@ -183,7 +202,11 @@ public class ThreadLocal<T> {
boolean isPresent() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
return map != null && map.getEntry(this) != null;
if (map != null && map != ThreadLocalMap.NOT_SUPPORTED) {
return map.getEntry(this) != null;
} else {
return false;
}
}
/**
@ -192,10 +215,10 @@ public class ThreadLocal<T> {
*
* @return the initial value
*/
private T setInitialValue() {
private T setInitialValue(Thread t) {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
assert map != ThreadLocalMap.NOT_SUPPORTED;
if (map != null) {
map.set(this, value);
} else {
@ -215,10 +238,25 @@ public class ThreadLocal<T> {
*
* @param value the value to be stored in the current thread's copy of
* this thread-local.
*
* @throws UnsupportedOperationException if the current thread is not
* allowed to set its copy of thread-local variables
*
* @see Thread.Builder#allowSetThreadLocals(boolean)
*/
public void set(T value) {
Thread t = Thread.currentThread();
set(Thread.currentThread(), value);
}
void setCarrierThreadLocal(T value) {
set(Thread.currentCarrierThread(), value);
}
private void set(Thread t, T value) {
ThreadLocalMap map = getMap(t);
if (map == ThreadLocalMap.NOT_SUPPORTED) {
throw new UnsupportedOperationException();
}
if (map != null) {
map.set(this, value);
} else {
@ -239,7 +277,7 @@ public class ThreadLocal<T> {
*/
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null) {
if (m != null && m != ThreadLocalMap.NOT_SUPPORTED) {
m.remove(this);
}
}
@ -337,6 +375,9 @@ public class ThreadLocal<T> {
}
}
// Placeholder when thread locals not supported
static final ThreadLocalMap NOT_SUPPORTED = new ThreadLocalMap();
/**
* The initial capacity -- MUST be a power of two.
*/
@ -379,6 +420,12 @@ public class ThreadLocal<T> {
return ((i - 1 >= 0) ? i - 1 : len - 1);
}
/**
* Construct a new map without a table.
*/
private ThreadLocalMap() {
}
/**
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
@ -421,6 +468,13 @@ public class ThreadLocal<T> {
}
}
/**
* Returns the number of elements in the map.
*/
int size() {
return size;
}
/**
* Get the entry associated with key. This method
* itself handles only the fast path: a direct hit of existing