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