1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package java.lang;
18
19import java.lang.ref.Reference;
20import java.lang.ref.WeakReference;
21import java.util.concurrent.atomic.AtomicInteger;
22
23/**
24 * Implements a thread-local storage, that is, a variable for which each thread
25 * has its own value. All threads share the same {@code ThreadLocal} object,
26 * but each sees a different value when accessing it, and changes made by one
27 * thread do not affect the other threads. The implementation supports
28 * {@code null} values.
29 *
30 * @see java.lang.Thread
31 * @author Bob Lee
32 */
33public class ThreadLocal<T> {
34
35    /* Thanks to Josh Bloch and Doug Lea for code reviews and impl advice. */
36
37    /**
38     * Creates a new thread-local variable.
39     */
40    public ThreadLocal() {}
41
42    /**
43     * Returns the value of this variable for the current thread. If an entry
44     * doesn't yet exist for this variable on this thread, this method will
45     * create an entry, populating the value with the result of
46     * {@link #initialValue()}.
47     *
48     * @return the current value of the variable for the calling thread.
49     */
50    @SuppressWarnings("unchecked")
51    public T get() {
52        // Optimized for the fast path.
53        Thread currentThread = Thread.currentThread();
54        Values values = values(currentThread);
55        if (values != null) {
56            Object[] table = values.table;
57            int index = hash & values.mask;
58            if (this.reference == table[index]) {
59                return (T) table[index + 1];
60            }
61        } else {
62            values = initializeValues(currentThread);
63        }
64
65        return (T) values.getAfterMiss(this);
66    }
67
68    /**
69     * Provides the initial value of this variable for the current thread.
70     * The default implementation returns {@code null}.
71     *
72     * @return the initial value of the variable.
73     */
74    protected T initialValue() {
75        return null;
76    }
77
78    /**
79     * Sets the value of this variable for the current thread. If set to
80     * {@code null}, the value will be set to null and the underlying entry will
81     * still be present.
82     *
83     * @param value the new value of the variable for the caller thread.
84     */
85    public void set(T value) {
86        Thread currentThread = Thread.currentThread();
87        Values values = values(currentThread);
88        if (values == null) {
89            values = initializeValues(currentThread);
90        }
91        values.put(this, value);
92    }
93
94    /**
95     * Removes the entry for this variable in the current thread. If this call
96     * is followed by a {@link #get()} before a {@link #set},
97     * {@code #get()} will call {@link #initialValue()} and create a new
98     * entry with the resulting value.
99     *
100     * @since 1.5
101     */
102    public void remove() {
103        Thread currentThread = Thread.currentThread();
104        Values values = values(currentThread);
105        if (values != null) {
106            values.remove(this);
107        }
108    }
109
110    /**
111     * Creates Values instance for this thread and variable type.
112     */
113    Values initializeValues(Thread current) {
114        return current.localValues = new Values();
115    }
116
117    /**
118     * Gets Values instance for this thread and variable type.
119     */
120    Values values(Thread current) {
121        return current.localValues;
122    }
123
124    /** Weak reference to this thread local instance. */
125    private final Reference<ThreadLocal<T>> reference
126            = new WeakReference<ThreadLocal<T>>(this);
127
128    /** Hash counter. */
129    private static AtomicInteger hashCounter = new AtomicInteger(0);
130
131    /**
132     * Internal hash. We deliberately don't bother with #hashCode().
133     * Hashes must be even. This ensures that the result of
134     * (hash & (table.length - 1)) points to a key and not a value.
135     *
136     * We increment by Doug Lea's Magic Number(TM) (*2 since keys are in
137     * every other bucket) to help prevent clustering.
138     */
139    private final int hash = hashCounter.getAndAdd(0x61c88647 * 2);
140
141    /**
142     * Per-thread map of ThreadLocal instances to values.
143     */
144    static class Values {
145
146        /**
147         * Size must always be a power of 2.
148         */
149        private static final int INITIAL_SIZE = 16;
150
151        /**
152         * Placeholder for deleted entries.
153         */
154        private static final Object TOMBSTONE = new Object();
155
156        /**
157         * Map entries. Contains alternating keys (ThreadLocal) and values.
158         * The length is always a power of 2.
159         */
160        private Object[] table;
161
162        /** Used to turn hashes into indices. */
163        private int mask;
164
165        /** Number of live entries. */
166        private int size;
167
168        /** Number of tombstones. */
169        private int tombstones;
170
171        /** Maximum number of live entries and tombstones. */
172        private int maximumLoad;
173
174        /** Points to the next cell to clean up. */
175        private int clean;
176
177        /**
178         * Constructs a new, empty instance.
179         */
180        Values() {
181            initializeTable(INITIAL_SIZE);
182            this.size = 0;
183            this.tombstones = 0;
184        }
185
186        /**
187         * Used for InheritableThreadLocals.
188         */
189        Values(Values fromParent) {
190            this.table = fromParent.table.clone();
191            this.mask = fromParent.mask;
192            this.size = fromParent.size;
193            this.tombstones = fromParent.tombstones;
194            this.maximumLoad = fromParent.maximumLoad;
195            this.clean = fromParent.clean;
196            inheritValues(fromParent);
197        }
198
199        /**
200         * Inherits values from a parent thread.
201         */
202        @SuppressWarnings({"unchecked"})
203        private void inheritValues(Values fromParent) {
204            // Transfer values from parent to child thread.
205            Object[] table = this.table;
206            for (int i = table.length - 2; i >= 0; i -= 2) {
207                Object k = table[i];
208
209                if (k == null || k == TOMBSTONE) {
210                    // Skip this entry.
211                    continue;
212                }
213
214                // The table can only contain null, tombstones and references.
215                Reference<InheritableThreadLocal<?>> reference
216                        = (Reference<InheritableThreadLocal<?>>) k;
217                // Raw type enables us to pass in an Object below.
218                InheritableThreadLocal key = reference.get();
219                if (key != null) {
220                    // Replace value with filtered value.
221                    // We should just let exceptions bubble out and tank
222                    // the thread creation
223                    table[i + 1] = key.childValue(fromParent.table[i + 1]);
224                } else {
225                    // The key was reclaimed.
226                    table[i] = TOMBSTONE;
227                    table[i + 1] = null;
228                    fromParent.table[i] = TOMBSTONE;
229                    fromParent.table[i + 1] = null;
230
231                    tombstones++;
232                    fromParent.tombstones++;
233
234                    size--;
235                    fromParent.size--;
236                }
237            }
238        }
239
240        /**
241         * Creates a new, empty table with the given capacity.
242         */
243        private void initializeTable(int capacity) {
244            this.table = new Object[capacity * 2];
245            this.mask = table.length - 1;
246            this.clean = 0;
247            this.maximumLoad = capacity * 2 / 3; // 2/3
248        }
249
250        /**
251         * Cleans up after garbage-collected thread locals.
252         */
253        private void cleanUp() {
254            if (rehash()) {
255                // If we rehashed, we needn't clean up (clean up happens as
256                // a side effect).
257                return;
258            }
259
260            if (size == 0) {
261                // No live entries == nothing to clean.
262                return;
263            }
264
265            // Clean log(table.length) entries picking up where we left off
266            // last time.
267            int index = clean;
268            Object[] table = this.table;
269            for (int counter = table.length; counter > 0; counter >>= 1,
270                    index = next(index)) {
271                Object k = table[index];
272
273                if (k == TOMBSTONE || k == null) {
274                    continue; // on to next entry
275                }
276
277                // The table can only contain null, tombstones and references.
278                @SuppressWarnings("unchecked")
279                Reference<ThreadLocal<?>> reference
280                        = (Reference<ThreadLocal<?>>) k;
281                if (reference.get() == null) {
282                    // This thread local was reclaimed by the garbage collector.
283                    table[index] = TOMBSTONE;
284                    table[index + 1] = null;
285                    tombstones++;
286                    size--;
287                }
288            }
289
290            // Point cursor to next index.
291            clean = index;
292        }
293
294        /**
295         * Rehashes the table, expanding or contracting it as necessary.
296         * Gets rid of tombstones. Returns true if a rehash occurred.
297         * We must rehash every time we fill a null slot; we depend on the
298         * presence of null slots to end searches (otherwise, we'll infinitely
299         * loop).
300         */
301        private boolean rehash() {
302            if (tombstones + size < maximumLoad) {
303                return false;
304            }
305
306            int capacity = table.length >> 1;
307
308            // Default to the same capacity. This will create a table of the
309            // same size and move over the live entries, analogous to a
310            // garbage collection. This should only happen if you churn a
311            // bunch of thread local garbage (removing and reinserting
312            // the same thread locals over and over will overwrite tombstones
313            // and not fill up the table).
314            int newCapacity = capacity;
315
316            if (size > (capacity >> 1)) {
317                // More than 1/2 filled w/ live entries.
318                // Double size.
319                newCapacity = capacity * 2;
320            }
321
322            Object[] oldTable = this.table;
323
324            // Allocate new table.
325            initializeTable(newCapacity);
326
327            // We won't have any tombstones after this.
328            this.tombstones = 0;
329
330            // If we have no live entries, we can quit here.
331            if (size == 0) {
332                return true;
333            }
334
335            // Move over entries.
336            for (int i = oldTable.length - 2; i >= 0; i -= 2) {
337                Object k = oldTable[i];
338                if (k == null || k == TOMBSTONE) {
339                    // Skip this entry.
340                    continue;
341                }
342
343                // The table can only contain null, tombstones and references.
344                @SuppressWarnings("unchecked")
345                Reference<ThreadLocal<?>> reference
346                        = (Reference<ThreadLocal<?>>) k;
347                ThreadLocal<?> key = reference.get();
348                if (key != null) {
349                    // Entry is still live. Move it over.
350                    add(key, oldTable[i + 1]);
351                } else {
352                    // The key was reclaimed.
353                    size--;
354                }
355            }
356
357            return true;
358        }
359
360        /**
361         * Adds an entry during rehashing. Compared to put(), this method
362         * doesn't have to clean up, check for existing entries, account for
363         * tombstones, etc.
364         */
365        void add(ThreadLocal<?> key, Object value) {
366            for (int index = key.hash & mask;; index = next(index)) {
367                Object k = table[index];
368                if (k == null) {
369                    table[index] = key.reference;
370                    table[index + 1] = value;
371                    return;
372                }
373            }
374        }
375
376        /**
377         * Sets entry for given ThreadLocal to given value, creating an
378         * entry if necessary.
379         */
380        void put(ThreadLocal<?> key, Object value) {
381            cleanUp();
382
383            // Keep track of first tombstone. That's where we want to go back
384            // and add an entry if necessary.
385            int firstTombstone = -1;
386
387            for (int index = key.hash & mask;; index = next(index)) {
388                Object k = table[index];
389
390                if (k == key.reference) {
391                    // Replace existing entry.
392                    table[index + 1] = value;
393                    return;
394                }
395
396                if (k == null) {
397                    if (firstTombstone == -1) {
398                        // Fill in null slot.
399                        table[index] = key.reference;
400                        table[index + 1] = value;
401                        size++;
402                        return;
403                    }
404
405                    // Go back and replace first tombstone.
406                    table[firstTombstone] = key.reference;
407                    table[firstTombstone + 1] = value;
408                    tombstones--;
409                    size++;
410                    return;
411                }
412
413                // Remember first tombstone.
414                if (firstTombstone == -1 && k == TOMBSTONE) {
415                    firstTombstone = index;
416                }
417            }
418        }
419
420        /**
421         * Gets value for given ThreadLocal after not finding it in the first
422         * slot.
423         */
424        Object getAfterMiss(ThreadLocal<?> key) {
425            Object[] table = this.table;
426            int index = key.hash & mask;
427
428            // If the first slot is empty, the search is over.
429            if (table[index] == null) {
430                Object value = key.initialValue();
431
432                // If the table is still the same and the slot is still empty...
433                if (this.table == table && table[index] == null) {
434                    table[index] = key.reference;
435                    table[index + 1] = value;
436                    size++;
437
438                    cleanUp();
439                    return value;
440                }
441
442                // The table changed during initialValue().
443                put(key, value);
444                return value;
445            }
446
447            // Keep track of first tombstone. That's where we want to go back
448            // and add an entry if necessary.
449            int firstTombstone = -1;
450
451            // Continue search.
452            for (index = next(index);; index = next(index)) {
453                Object reference = table[index];
454                if (reference == key.reference) {
455                    return table[index + 1];
456                }
457
458                // If no entry was found...
459                if (reference == null) {
460                    Object value = key.initialValue();
461
462                    // If the table is still the same...
463                    if (this.table == table) {
464                        // If we passed a tombstone and that slot still
465                        // contains a tombstone...
466                        if (firstTombstone > -1
467                                && table[firstTombstone] == TOMBSTONE) {
468                            table[firstTombstone] = key.reference;
469                            table[firstTombstone + 1] = value;
470                            tombstones--;
471                            size++;
472
473                            // No need to clean up here. We aren't filling
474                            // in a null slot.
475                            return value;
476                        }
477
478                        // If this slot is still empty...
479                        if (table[index] == null) {
480                            table[index] = key.reference;
481                            table[index + 1] = value;
482                            size++;
483
484                            cleanUp();
485                            return value;
486                        }
487                    }
488
489                    // The table changed during initialValue().
490                    put(key, value);
491                    return value;
492                }
493
494                if (firstTombstone == -1 && reference == TOMBSTONE) {
495                    // Keep track of this tombstone so we can overwrite it.
496                    firstTombstone = index;
497                }
498            }
499        }
500
501        /**
502         * Removes entry for the given ThreadLocal.
503         */
504        void remove(ThreadLocal<?> key) {
505            cleanUp();
506
507            for (int index = key.hash & mask;; index = next(index)) {
508                Object reference = table[index];
509
510                if (reference == key.reference) {
511                    // Success!
512                    table[index] = TOMBSTONE;
513                    table[index + 1] = null;
514                    tombstones++;
515                    size--;
516                    return;
517                }
518
519                if (reference == null) {
520                    // No entry found.
521                    return;
522                }
523            }
524        }
525
526        /**
527         * Gets the next index. If we're at the end of the table, we wrap back
528         * around to 0.
529         */
530        private int next(int index) {
531            return (index + 2) & mask;
532        }
533    }
534}
535