From bcc0780ddc022e2bf43b07be5f59cec081b5c89a Mon Sep 17 00:00:00 2001 From: Diego Date: Thu, 27 Sep 2018 09:26:38 -0300 Subject: avoid use an Kamon-defined holder object as that would prevent class unloading. --- .../src/main/scala/kamon/context/Storage.scala | 40 +++++++++------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/kamon-core/src/main/scala/kamon/context/Storage.scala b/kamon-core/src/main/scala/kamon/context/Storage.scala index f116142d..2b409592 100644 --- a/kamon-core/src/main/scala/kamon/context/Storage.scala +++ b/kamon-core/src/main/scala/kamon/context/Storage.scala @@ -1,5 +1,5 @@ /* ========================================================================================= - * Copyright © 2013-2017 the kamon project + * Copyright © 2013-2018 the kamon project * * 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 @@ -15,8 +15,6 @@ package kamon.context -import kamon.context.Storage.ThreadLocal.ContextHolder - trait Storage { def current(): Context def store(context: Context): Storage.Scope @@ -33,41 +31,37 @@ object Storage { * Wrapper that implements optimized {@link ThreadLocal} access pattern ideal for heavily used * ThreadLocals. * - * It is faster to use a mutable holder object and always perform ThreadLocal.get() and never use + *

It is faster to use a mutable holder object and always perform ThreadLocal.get() and never use * ThreadLocal.set(), because the value is more likely to be found in the ThreadLocalMap direct hash * slot and avoid the slow path ThreadLocalMap.getEntryAfterMiss(). * - * Important: this thread local will live in ThreadLocalMap forever, so use with care. - */ + *

Credit to @trask from the FastThreadLocal in glowroot. + * + *

One small change is that we don't use an kamon-defined holder object as that would prevent class unloading. + * + * */ class ThreadLocal extends Storage { - private val tls = new java.lang.ThreadLocal[ContextHolder]() { - override def initialValue() = new ContextHolder(Context.Empty) + private val tls = new java.lang.ThreadLocal[Array[AnyRef]]() { + override def initialValue(): Array[AnyRef] = + Array(Context.Empty) } override def current(): Context = - get() + tls.get()(0).asInstanceOf[Context] - override def store(context: Context): Scope = { - val newContext = context - val previousContext = get() - set(newContext) + override def store(newContext: Context): Scope = { + val ref = tls.get() + val previousContext = ref(0) + ref(0) = newContext new Scope { override def context: Context = newContext - override def close(): Unit = set(previousContext) + override def close(): Unit = ref(0) = previousContext } } - - private def get():Context = - tls.get().value - - private def set(value:Context) : Unit = - tls.get().value = value } object ThreadLocal { def apply(): ThreadLocal = new ThreadLocal() - - final class ContextHolder(var value:Context) } -} \ No newline at end of file +} -- cgit v1.2.3