mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
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:
parent
5212535a27
commit
9583e3657e
1133 changed files with 95935 additions and 8335 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue