src/java.base/share/classes/java/lang/ThreadLocal.java
author mr
Tue, 29 Oct 2019 08:26:55 -0700
changeset 58842 6c255334120d
parent 50719 106dc156ce6b
permissions -rw-r--r--
8232080: jlink plugins for vendor information and run-time options Reviewed-by: ihse, alanb, kvn, bobv, mchung
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
23010
6dadb192ad81 8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents: 22581
diff changeset
     2
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package java.lang;
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
    27
import jdk.internal.misc.TerminatingThreadLocal;
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
    28
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.lang.ref.*;
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    30
import java.util.Objects;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.concurrent.atomic.AtomicInteger;
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    32
import java.util.function.Supplier;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * This class provides thread-local variables.  These variables differ from
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * their normal counterparts in that each thread that accesses one (via its
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    37
 * {@code get} or {@code set} method) has its own, independently initialized
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    38
 * copy of the variable.  {@code ThreadLocal} instances are typically private
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * static fields in classes that wish to associate state with a thread (e.g.,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * a user ID or Transaction ID).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * <p>For example, the class below generates unique identifiers local to each
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * thread.
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    44
 * A thread's id is assigned the first time it invokes {@code ThreadId.get()}
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * and remains unchanged on subsequent calls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * import java.util.concurrent.atomic.AtomicInteger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * public class ThreadId {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 *     // Atomic integer containing the next thread ID to be assigned
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 *     private static final AtomicInteger nextId = new AtomicInteger(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *     // Thread local variable containing each thread's ID
14014
da3648e13e67 8000269: Cleanup javadoc warnings
alanb
parents: 11275
diff changeset
    54
 *     private static final ThreadLocal&lt;Integer&gt; threadId =
da3648e13e67 8000269: Cleanup javadoc warnings
alanb
parents: 11275
diff changeset
    55
 *         new ThreadLocal&lt;Integer&gt;() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 *             &#64;Override protected Integer initialValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *                 return nextId.getAndIncrement();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 *         }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *     };
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *     // Returns the current thread's unique ID, assigning it if necessary
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 *     public static int get() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 *         return threadId.get();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * </pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * <p>Each thread holds an implicit reference to its copy of a thread-local
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
    68
 * variable as long as the thread is alive and the {@code ThreadLocal}
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * instance is accessible; after a thread goes away, all of its copies of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * thread-local instances are subject to garbage collection (unless other
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * references to these copies exist).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * @author  Josh Bloch and Doug Lea
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * @since   1.2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
public class ThreadLocal<T> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     * ThreadLocals rely on per-thread linear-probe hash maps attached
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
     * to each thread (Thread.threadLocals and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
     * inheritableThreadLocals).  The ThreadLocal objects act as keys,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
     * searched via threadLocalHashCode.  This is a custom hash code
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
     * (useful only within ThreadLocalMaps) that eliminates collisions
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
     * in the common case where consecutively constructed ThreadLocals
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     * are used by the same threads, while remaining well-behaved in
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
     * less common cases.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private final int threadLocalHashCode = nextHashCode();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     * The next hash code to be given out. Updated atomically. Starts at
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    private static AtomicInteger nextHashCode =
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
        new AtomicInteger();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     * The difference between successively generated hash codes - turns
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * implicit sequential thread-local IDs into near-optimally spread
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * multiplicative hash values for power-of-two-sized tables.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private static final int HASH_INCREMENT = 0x61c88647;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * Returns the next hash code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    private static int nextHashCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        return nextHashCode.getAndAdd(HASH_INCREMENT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
     * Returns the current thread's "initial value" for this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
     * thread-local variable.  This method will be invoked the first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * time a thread accesses the variable with the {@link #get}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * method, unless the thread previously invoked the {@link #set}
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   115
     * method, in which case the {@code initialValue} method will not
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * be invoked for the thread.  Normally, this method is invoked at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * most once per thread, but it may be invoked again in case of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     * subsequent invocations of {@link #remove} followed by {@link #get}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
     *
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   120
     * <p>This implementation simply returns {@code null}; if the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
     * programmer desires thread-local variables to have an initial
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   122
     * value other than {@code null}, {@code ThreadLocal} must be
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * subclassed, and this method overridden.  Typically, an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * anonymous inner class will be used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * @return the initial value for this thread-local
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    protected T initialValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    /**
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   133
     * Creates a thread local variable. The initial value of the variable is
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   134
     * determined by invoking the {@code get} method on the {@code Supplier}.
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   135
     *
18776
c17100862d86 8019862: Fix doclint errors in java.lang.*.
bpb
parents: 14770
diff changeset
   136
     * @param <S> the type of the thread local's value
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   137
     * @param supplier the supplier to be used to determine the initial value
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   138
     * @return a new thread local variable
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   139
     * @throws NullPointerException if the specified supplier is null
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   140
     * @since 1.8
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   141
     */
18776
c17100862d86 8019862: Fix doclint errors in java.lang.*.
bpb
parents: 14770
diff changeset
   142
    public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   143
        return new SuppliedThreadLocal<>(supplier);
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   144
    }
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   145
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   146
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
     * Creates a thread local variable.
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   148
     * @see #withInitial(java.util.function.Supplier)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    public ThreadLocal() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     * Returns the value in the current thread's copy of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     * thread-local variable.  If the variable has no value for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
     * current thread, it is first initialized to the value returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
     * by an invocation of the {@link #initialValue} method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     * @return the current thread's value of this thread-local
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    public T get() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
        Thread t = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        ThreadLocalMap map = getMap(t);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        if (map != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            ThreadLocalMap.Entry e = map.getEntry(this);
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   166
            if (e != null) {
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   167
                @SuppressWarnings("unchecked")
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   168
                T result = (T)e.value;
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   169
                return result;
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   170
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        return setInitialValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    /**
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   176
     * Returns {@code true} if there is a value in the current thread's copy of
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   177
     * this thread-local variable, even if that values is {@code null}.
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   178
     *
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   179
     * @return {@code true} if current thread has associated value in this
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   180
     *         thread-local variable; {@code false} if not
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   181
     */
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   182
    boolean isPresent() {
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   183
        Thread t = Thread.currentThread();
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   184
        ThreadLocalMap map = getMap(t);
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   185
        return map != null && map.getEntry(this) != null;
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   186
    }
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   187
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   188
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     * Variant of set() to establish initialValue. Used instead
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
     * of set() in case user has overridden the set() method.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
     * @return the initial value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    private T setInitialValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        T value = initialValue();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        Thread t = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        ThreadLocalMap map = getMap(t);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   198
        if (map != null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            map.set(this, value);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   200
        } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            createMap(t, value);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   202
        }
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   203
        if (this instanceof TerminatingThreadLocal) {
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   204
            TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   205
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
     * Sets the current thread's copy of this thread-local variable
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * to the specified value.  Most subclasses will have no need to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * override this method, relying solely on the {@link #initialValue}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     * method to set the values of thread-locals.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
     * @param value the value to be stored in the current thread's copy of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
     *        this thread-local.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
    public void set(T value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        Thread t = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        ThreadLocalMap map = getMap(t);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   221
        if (map != null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            map.set(this, value);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   223
        } else {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
            createMap(t, value);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   225
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     * Removes the current thread's value for this thread-local
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
     * variable.  If this thread-local variable is subsequently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
     * {@linkplain #get read} by the current thread, its value will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
     * reinitialized by invoking its {@link #initialValue} method,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
     * unless its value is {@linkplain #set set} by the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
     * in the interim.  This may result in multiple invocations of the
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   235
     * {@code initialValue} method in the current thread.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     public void remove() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
         ThreadLocalMap m = getMap(Thread.currentThread());
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   241
         if (m != null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
             m.remove(this);
50719
106dc156ce6b 8202788: Explicitly reclaim cached thread-local direct buffers at thread exit
plevart
parents: 47216
diff changeset
   243
         }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * Get the map associated with a ThreadLocal. Overridden in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     * InheritableThreadLocal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     * @param  t the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     * @return the map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    ThreadLocalMap getMap(Thread t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        return t.threadLocals;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * Create the map associated with a ThreadLocal. Overridden in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     * InheritableThreadLocal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     * @param t the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     * @param firstValue value for the initial entry of the map
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
    void createMap(Thread t, T firstValue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        t.threadLocals = new ThreadLocalMap(this, firstValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * Factory method to create map of inherited thread locals.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * Designed to be called only from Thread constructor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
     * @param  parentMap the map associated with parent thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
     * @return a map containing the parent's inheritable bindings
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        return new ThreadLocalMap(parentMap);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
     * Method childValue is visibly defined in subclass
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
     * InheritableThreadLocal, but is internally defined here for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     * sake of providing createInheritedMap factory method without
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * needing to subclass the map class in InheritableThreadLocal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     * This technique is preferable to the alternative of embedding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     * instanceof tests in methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    T childValue(T parentValue) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        throw new UnsupportedOperationException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    /**
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   292
     * An extension of ThreadLocal that obtains its initial value from
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   293
     * the specified {@code Supplier}.
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   294
     */
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   295
    static final class SuppliedThreadLocal<T> extends ThreadLocal<T> {
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   296
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   297
        private final Supplier<? extends T> supplier;
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   298
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   299
        SuppliedThreadLocal(Supplier<? extends T> supplier) {
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   300
            this.supplier = Objects.requireNonNull(supplier);
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   301
        }
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   302
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   303
        @Override
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   304
        protected T initialValue() {
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   305
            return supplier.get();
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   306
        }
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   307
    }
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   308
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   309
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * ThreadLocalMap is a customized hash map suitable only for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     * maintaining thread local values. No operations are exported
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
     * outside of the ThreadLocal class. The class is package private to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
     * allow declaration of fields in class Thread.  To help deal with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
     * very large and long-lived usages, the hash table entries use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
     * WeakReferences for keys. However, since reference queues are not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
     * used, stale entries are guaranteed to be removed only when
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
     * the table starts running out of space.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    static class ThreadLocalMap {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
         * The entries in this hash map extend WeakReference, using
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
         * its main ref field as the key (which is always a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
         * == null) mean that the key is no longer referenced, so the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
         * entry can be expunged from table.  Such entries are referred to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
         * as "stale entries" in the code that follows.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   329
        static class Entry extends WeakReference<ThreadLocal<?>> {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
            /** The value associated with this ThreadLocal. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
            Object value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   333
            Entry(ThreadLocal<?> k, Object v) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                super(k);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                value = v;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
         * The initial capacity -- MUST be a power of two.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        private static final int INITIAL_CAPACITY = 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
         * The table, resized as necessary.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
         * table.length MUST always be a power of two.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        private Entry[] table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
         * The number of entries in the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        private int size = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
         * The next size value at which to resize.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
        private int threshold; // Default to 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
         * Set the resize threshold to maintain at worst a 2/3 load factor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        private void setThreshold(int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            threshold = len * 2 / 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
         * Increment i modulo len.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        private static int nextIndex(int i, int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            return ((i + 1 < len) ? i + 1 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
         * Decrement i modulo len.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        private static int prevIndex(int i, int len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            return ((i - 1 >= 0) ? i - 1 : len - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
         * Construct a new map initially containing (firstKey, firstValue).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
         * ThreadLocalMaps are constructed lazily, so we only create
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
         * one when we have at least one entry to put in it.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   386
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            table = new Entry[INITIAL_CAPACITY];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
            table[i] = new Entry(firstKey, firstValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
            size = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
            setThreshold(INITIAL_CAPACITY);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
         * Construct a new map including all Inheritable ThreadLocals
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
         * from given parent map. Called only by createInheritedMap.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
         * @param parentMap the map associated with parent thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        private ThreadLocalMap(ThreadLocalMap parentMap) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            Entry[] parentTable = parentMap.table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            int len = parentTable.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
            setThreshold(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            table = new Entry[len];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
22581
e868cde95050 8032779: Update code in java.lang to use newer language features
psandoz
parents: 18776
diff changeset
   406
            for (Entry e : parentTable) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
                if (e != null) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   408
                    @SuppressWarnings("unchecked")
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   409
                    ThreadLocal<Object> key = (ThreadLocal<Object>) e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                    if (key != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                        Object value = key.childValue(e.value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                        Entry c = new Entry(key, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                        int h = key.threadLocalHashCode & (len - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                        while (table[h] != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                            h = nextIndex(h, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
                        table[h] = c;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
                        size++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
         * Get the entry associated with key.  This method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
         * itself handles only the fast path: a direct hit of existing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
         * key. It otherwise relays to getEntryAfterMiss.  This is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
         * designed to maximize performance for direct hits, in part
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
         * by making this method readily inlinable.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
         * @param  key the thread local object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
         * @return the entry associated with key, or null if no such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   433
        private Entry getEntry(ThreadLocal<?> key) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            int i = key.threadLocalHashCode & (table.length - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
            Entry e = table[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
            if (e != null && e.get() == key)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                return getEntryAfterMiss(key, i, e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
         * Version of getEntry method for use when key is not found in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
         * its direct hash slot.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
         * @param  key the thread local object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
         * @param  i the table index for key's hash code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
         * @param  e the entry at table[i]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
         * @return the entry associated with key, or null if no such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   451
        private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            while (e != null) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   456
                ThreadLocal<?> k = e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                if (k == key)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                    return e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                if (k == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                    expungeStaleEntry(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                    i = nextIndex(i, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                e = tab[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
         * Set the value associated with key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
         * @param key the thread local object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
         * @param value the value to be set
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   474
        private void set(ThreadLocal<?> key, Object value) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            // We don't use a fast path as with get() because it is at
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
            // least as common to use set() to create new entries as
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            // it is to replace existing ones, in which case, a fast
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            // path would fail more often than not.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            int i = key.threadLocalHashCode & (len-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
            for (Entry e = tab[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                 e != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                 e = tab[i = nextIndex(i, len)]) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   488
                ThreadLocal<?> k = e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
                if (k == key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                    e.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                if (k == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                    replaceStaleEntry(key, value, i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            tab[i] = new Entry(key, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            int sz = ++size;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
                rehash();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
         * Remove the entry for key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   510
        private void remove(ThreadLocal<?> key) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
            int i = key.threadLocalHashCode & (len-1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            for (Entry e = tab[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
                 e != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                 e = tab[i = nextIndex(i, len)]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                if (e.get() == key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                    e.clear();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                    expungeStaleEntry(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
         * Replace a stale entry encountered during a set operation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
         * with an entry for the specified key.  The value passed in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
         * the value parameter is stored in the entry, whether or not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
         * an entry already exists for the specified key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
         * As a side effect, this method expunges all stale entries in the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
         * "run" containing the stale entry.  (A run is a sequence of entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
         * between two null slots.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
         * @param  key the key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
         * @param  value the value to be associated with key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
         * @param  staleSlot index of the first stale entry encountered while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
         *         searching for key.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
         */
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   540
        private void replaceStaleEntry(ThreadLocal<?> key, Object value,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
                                       int staleSlot) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            Entry e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
            // Back up to check for prior stale entry in current run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            // We clean out whole runs at a time to avoid continual
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
            // incremental rehashing due to garbage collector freeing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            // up refs in bunches (i.e., whenever the collector runs).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            int slotToExpunge = staleSlot;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
            for (int i = prevIndex(staleSlot, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
                 (e = tab[i]) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                 i = prevIndex(i, len))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                if (e.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
                    slotToExpunge = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
            // Find either the key or trailing null slot of run, whichever
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            // occurs first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
            for (int i = nextIndex(staleSlot, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
                 (e = tab[i]) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                 i = nextIndex(i, len)) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   562
                ThreadLocal<?> k = e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
                // If we find key, then we need to swap it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
                // with the stale entry to maintain hash table order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                // The newly stale slot, or any other stale slot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                // encountered above it, can then be sent to expungeStaleEntry
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                // to remove or rehash all of the other entries in run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
                if (k == key) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                    e.value = value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
                    tab[i] = tab[staleSlot];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                    tab[staleSlot] = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                    // Start expunge at preceding stale entry if it exists
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                    if (slotToExpunge == staleSlot)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                        slotToExpunge = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
                    cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
                // If we didn't find stale entry on backward scan, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
                // first stale entry seen while scanning for key is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
                // first still present in the run.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
                if (k == null && slotToExpunge == staleSlot)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
                    slotToExpunge = i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            // If key not found, put new entry in stale slot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
            tab[staleSlot].value = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            tab[staleSlot] = new Entry(key, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
            // If there are any other stale entries in run, expunge them
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            if (slotToExpunge != staleSlot)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                cleanSomeSlots(expungeStaleEntry(slotToExpunge), len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
         * Expunge a stale entry by rehashing any possibly colliding entries
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
         * lying between staleSlot and the next null slot.  This also expunges
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
         * any other stale entries encountered before the trailing null.  See
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
         * Knuth, Section 6.4
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
         * @param staleSlot index of slot known to have null key
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
         * @return the index of the next null slot after staleSlot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
         * (all between staleSlot and this slot will have been checked
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
         * for expunging).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        private int expungeStaleEntry(int staleSlot) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            // expunge entry at staleSlot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
            tab[staleSlot].value = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
            tab[staleSlot] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            size--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            // Rehash until we encounter null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
            Entry e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
            int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
            for (i = nextIndex(staleSlot, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                 (e = tab[i]) != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                 i = nextIndex(i, len)) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   624
                ThreadLocal<?> k = e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                if (k == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                    e.value = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
                    tab[i] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
                    size--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
                    int h = k.threadLocalHashCode & (len - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                    if (h != i) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                        tab[i] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                        // Unlike Knuth 6.4 Algorithm R, we must scan until
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                        // null because multiple entries could have been stale.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                        while (tab[h] != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
                            h = nextIndex(h, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
                        tab[h] = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
         * Heuristically scan some cells looking for stale entries.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
         * This is invoked when either a new element is added, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
         * another stale one has been expunged. It performs a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
         * logarithmic number of scans, as a balance between no
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
         * scanning (fast but retains garbage) and a number of scans
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
         * proportional to number of elements, that would find all
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
         * garbage but would cause some insertions to take O(n) time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
         * @param i a position known NOT to hold a stale entry. The
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
         * scan starts at the element after i.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
         *
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   657
         * @param n scan control: {@code log2(n)} cells are scanned,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
         * unless a stale entry is found, in which case
14770
1b609703adbf 8003246: Add InitialValue Supplier to ThreadLocal
akhil
parents: 14342
diff changeset
   659
         * {@code log2(table.length)-1} additional cells are scanned.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
         * When called from insertions, this parameter is the number
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
         * of elements, but when from replaceStaleEntry, it is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
         * table length. (Note: all this could be changed to be either
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
         * more or less aggressive by weighting n instead of just
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
         * using straight log n. But this version is simple, fast, and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
         * seems to work well.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
         * @return true if any stale entries have been removed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
        private boolean cleanSomeSlots(int i, int n) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            boolean removed = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
            do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                i = nextIndex(i, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                Entry e = tab[i];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                if (e != null && e.get() == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    n = len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                    removed = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    i = expungeStaleEntry(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
            } while ( (n >>>= 1) != 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            return removed;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
         * Re-pack and/or re-size the table. First scan the entire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
         * table removing stale entries. If this doesn't sufficiently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
         * shrink the size of the table, double the table size.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        private void rehash() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
            expungeStaleEntries();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            // Use lower threshold for doubling to avoid hysteresis
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
            if (size >= threshold - threshold / 4)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                resize();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
         * Double the capacity of the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        private void resize() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
            Entry[] oldTab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            int oldLen = oldTab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
            int newLen = oldLen * 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
            Entry[] newTab = new Entry[newLen];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            int count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
22581
e868cde95050 8032779: Update code in java.lang to use newer language features
psandoz
parents: 18776
diff changeset
   708
            for (Entry e : oldTab) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                if (e != null) {
11275
7cb0861d512f 7117612: Miscellaneous warnings in java.lang
omajid
parents: 5506
diff changeset
   710
                    ThreadLocal<?> k = e.get();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                    if (k == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                        e.value = null; // Help the GC
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                        int h = k.threadLocalHashCode & (newLen - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                        while (newTab[h] != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
                            h = nextIndex(h, newLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                        newTab[h] = e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                        count++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
            setThreshold(newLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
            size = count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            table = newTab;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
         * Expunge all stale entries in the table.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
        private void expungeStaleEntries() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
            Entry[] tab = table;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            int len = tab.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            for (int j = 0; j < len; j++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                Entry e = tab[j];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
                if (e != null && e.get() == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                    expungeStaleEntry(j);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
}