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