All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.oschina.j2cache.hibernate4.util.VicariousThreadLocal Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2015-2017.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.oschina.j2cache.hibernate4.util; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; public class VicariousThreadLocal extends ThreadLocal { private static final ThreadLocal> weakThread = new ThreadLocal>(); static WeakReference currentThreadRef() { WeakReference ref = weakThread.get(); if (ref == null) { ref = new WeakReference(Thread.currentThread()); weakThread.set(ref); } return ref; } private static final Object UNINITIALISED = new Object(); private final ThreadLocal> local = new ThreadLocal>(); private volatile Holder strongRefs; private static final AtomicReferenceFieldUpdater strongRefsUpdater = AtomicReferenceFieldUpdater.newUpdater(VicariousThreadLocal.class, Holder.class, "strongRefs"); private final ReferenceQueue queue = new ReferenceQueue(); public VicariousThreadLocal() { } @SuppressWarnings("unchecked") @Override public T get() { final Holder holder; WeakReference ref = local.get(); if (ref != null) { holder = ref.get(); Object value = holder.value; if (value != UNINITIALISED) { return (T) value; } } else { holder = createHolder(); } T value = initialValue(); holder.value = value; return value; } @Override public void set(T value) { WeakReference ref = local.get(); final Holder holder = ref != null ? ref.get() : createHolder(); holder.value = value; } private Holder createHolder() { poll(); Holder holder = new Holder(queue); WeakReference ref = new WeakReference(holder); Holder old; do { old = strongRefs; holder.next = old; } while (!strongRefsUpdater.compareAndSet(this, old, holder)); local.set(ref); return holder; } @Override public void remove() { WeakReference ref = local.get(); if (ref != null) { ref.get().value = UNINITIALISED; } } /** * Check if any strong references need should be removed due to thread exit. */ public void poll() { synchronized (queue) { // Remove queued references. // (Is this better inside or out?) if (queue.poll() == null) { // Nothing to do. return; } while (queue.poll() != null) { // Discard. } // Remove any dead holders. Holder first = strongRefs; if (first == null) { // Unlikely... return; } Holder link = first; Holder next = link.next; while (next != null) { if (next.get() == null) { next = next.next; link.next = next; } else { link = next; next = next.next; } } // Remove dead head, possibly. if (first.get() == null) { if (!strongRefsUpdater.weakCompareAndSet( this, first, first.next )) { // Something else has come along. // Just null out - next search will remove it. first.value = null; } } } } /** * Holds strong reference to a thread-local value. * The WeakReference is to a thread-local representing the current thread. */ private static class Holder extends WeakReference { /** * Construct a new holder for the current thread. */ Holder(ReferenceQueue queue) { super(currentThreadRef(), queue); } /** * Next holder in chain for this thread-local. */ Holder next; /** * Current thread-local value. * {@link #UNINITIALISED} represents an uninitialised value. */ Object value = UNINITIALISED; } }