LOG4NET-554 Use AsyncLocal for LogicalThreadContext

Patch by Thomas Clegg.

closes #52



Project: http://git-wip-us.apache.org/repos/asf/logging-log4net/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4net/commit/201ad1ae
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4net/tree/201ad1ae
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4net/diff/201ad1ae

Branch: refs/heads/master
Commit: 201ad1ae3ced298e77469f99e548244a7f772b06
Parents: c0b95f9
Author: Stefan Bodewig <bode...@apache.org>
Authored: Fri Mar 3 21:45:41 2017 +0000
Committer: Stefan Bodewig <bode...@apache.org>
Committed: Fri Mar 3 21:45:41 2017 +0000

----------------------------------------------------------------------
 netstandard/log4net.tests/log4net.tests.xproj   |  1 +
 netstandard/log4net.tests/project.json          |  1 +
 netstandard/log4net/log4net.xproj               |  6 ++--
 netstandard/log4net/project.json                |  3 --
 src/Core/LoggingEvent.cs                        |  6 ++--
 src/Util/LogicalThreadContextProperties.cs      | 31 ++++++++++++++------
 .../PropertyPatternConverter.cs                 |  2 +-
 src/site/xdoc/release/framework-support.xml     | 10 +++++--
 tests/src/Context/LogicalThreadContextTest.cs   |  2 +-
 tests/src/Utils.cs                              |  2 +-
 10 files changed, 40 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/netstandard/log4net.tests/log4net.tests.xproj
----------------------------------------------------------------------
diff --git a/netstandard/log4net.tests/log4net.tests.xproj 
b/netstandard/log4net.tests/log4net.tests.xproj
index 00fecb3..92eecae 100644
--- a/netstandard/log4net.tests/log4net.tests.xproj
+++ b/netstandard/log4net.tests/log4net.tests.xproj
@@ -36,6 +36,7 @@ limitations under the License.
     <Compile Include="../../tests/src/Appender/SmtpPickupDirAppenderTest.cs" />
     <Compile Include="../../tests/src/Appender/StringAppender.cs" />
     <Compile Include="../../tests/src/Appender/TraceAppenderTest.cs" />
+    <Compile Include="../../tests/src/Context/LogicalThreadContextTest.cs" />
     <Compile Include="../../tests/src/Context/ThreadContextTest.cs" />
     <Compile Include="../../tests/src/Core/**/*.cs" />
     <Compile Include="../../tests/src/DateFormatter/**/*.cs" />

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/netstandard/log4net.tests/project.json
----------------------------------------------------------------------
diff --git a/netstandard/log4net.tests/project.json 
b/netstandard/log4net.tests/project.json
index 1e2396d..49af8d7 100644
--- a/netstandard/log4net.tests/project.json
+++ b/netstandard/log4net.tests/project.json
@@ -11,6 +11,7 @@
       "../../tests/src/Appender/SmtpPickupDirAppenderTest.cs",
       "../../tests/src/Appender/StringAppender.cs",
       "../../tests/src/Appender/TraceAppenderTest.cs",
+      "../../tests/src/Context/LogicalThreadContextTest.cs",
       "../../tests/src/Context/ThreadContextTest.cs",
       "../../tests/src/Core/**/*.cs",
       "../../tests/src/DateFormatter/**/*.cs",

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/netstandard/log4net/log4net.xproj
----------------------------------------------------------------------
diff --git a/netstandard/log4net/log4net.xproj 
b/netstandard/log4net/log4net.xproj
index ff371a0..083a7a4 100644
--- a/netstandard/log4net/log4net.xproj
+++ b/netstandard/log4net/log4net.xproj
@@ -161,7 +161,7 @@ limitations under the License.
     <Compile Include="../../src/Layout/XmlLayout.cs" />
     <Compile Include="../../src/Layout/XmlLayoutBase.cs" />
     <Compile Include="../../src/Layout/XmlLayoutSchemaLog4j.cs" />
-    <!--<Compile Include="../../src/LogicalThreadContext.cs" />-->
+    <Compile Include="../../src/LogicalThreadContext.cs" />
     <Compile Include="../../src/LogManager.cs" />
     <Compile Include="../../src/MDC.cs" />
     <Compile Include="../../src/NDC.cs" />
@@ -201,9 +201,9 @@ limitations under the License.
     <Compile Include="../../src/Util/ILogExtensions.cs" />
     <Compile Include="../../src/Util/LevelMapping.cs" />
     <Compile Include="../../src/Util/LevelMappingEntry.cs" />
-    <!--<Compile Include="../../src/Util/LogicalThreadContextProperties.cs" 
/>-->
+    <Compile Include="../../src/Util/LogicalThreadContextProperties.cs" />
     <Compile Include="../../src/Util/LogicalThreadContextStack.cs" />
-    <!--<Compile Include="../../src/Util/LogicalThreadContextStacks.cs" />-->
+    <Compile Include="../../src/Util/LogicalThreadContextStacks.cs" />
     <Compile Include="../../src/Util/LogLog.cs" />
     <!--<Compile Include="../../src/Util/NativeError.cs" />-->
     <Compile Include="../../src/Util/NullDictionaryEnumerator.cs" />

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/netstandard/log4net/project.json
----------------------------------------------------------------------
diff --git a/netstandard/log4net/project.json b/netstandard/log4net/project.json
index 75978e5..53164d9 100644
--- a/netstandard/log4net/project.json
+++ b/netstandard/log4net/project.json
@@ -16,7 +16,6 @@
             "../../src/Appender/NetSendAppender.cs",
             "../../src/Appender/RemotingAppender.cs",
             "../../src/Appender/SmtpAppender.cs",
-            "../../src/LogicalThreadContext.cs",
             "../../src/Config/DOMConfigurator.cs",
             "../../src/Config/DOMConfiguratorAttribute.cs",
             "../../src/Config/Log4NetConfigurationSectionHandler.cs",
@@ -30,8 +29,6 @@
             "../../src/Plugin/RemoteLoggingServerPlugin.cs",
             
"../../src/Util/PatternStringConverters/AppSettingPatternConverter.cs",
             
"../../src/Util/PatternStringConverters/EnvironmentFolderPathPatternConverter.cs",
-            "../../src/Util/LogicalThreadContextProperties.cs",
-            "../../src/Util/LogicalThreadContextStacks.cs",
             "../../src/Util/NativeError.cs",
             "../../src/Util/WindowsSecurityContext.cs"
           ]

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/src/Core/LoggingEvent.cs
----------------------------------------------------------------------
diff --git a/src/Core/LoggingEvent.cs b/src/Core/LoggingEvent.cs
index fb9a506..eb54a60 100644
--- a/src/Core/LoggingEvent.cs
+++ b/src/Core/LoggingEvent.cs
@@ -461,7 +461,7 @@ namespace log4net.Core
 
                #region Protected Instance Constructors
 
-#if !(NETCF || NETSTANDARD1_3)
+#if !NETCF
 
                /// <summary>
                /// Serialization constructor
@@ -814,7 +814,7 @@ namespace log4net.Core
                        {
                                if (m_data.ThreadName == null && 
this.m_cacheUpdatable)
                                {
-#if NETCF || NETSTANDARD1_3
+#if NETCF
                                        // Get thread ID only
                                        m_data.ThreadName = 
SystemInfo.CurrentThreadId.ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
 #else
@@ -1394,7 +1394,7 @@ namespace log4net.Core
                        {
                                compositeProperties.Add(m_eventProperties);
                        }
-#if !(NETCF || NETSTANDARD1_3)
+#if !NETCF
                        PropertiesDictionary logicalThreadProperties = 
LogicalThreadContext.Properties.GetProperties(false);
                        if (logicalThreadProperties != null)
                        {

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/src/Util/LogicalThreadContextProperties.cs
----------------------------------------------------------------------
diff --git a/src/Util/LogicalThreadContextProperties.cs 
b/src/Util/LogicalThreadContextProperties.cs
index fb9684f..904229d 100644
--- a/src/Util/LogicalThreadContextProperties.cs
+++ b/src/Util/LogicalThreadContextProperties.cs
@@ -21,8 +21,13 @@
 #if !NETCF
 
 using System;
+#if !NETSTANDARD1_3
 using System.Runtime.Remoting.Messaging;
+#endif
 using System.Security;
+#if NETSTANDARD1_3
+using System.Threading;
+#endif
 
 namespace log4net.Util
 {
@@ -49,7 +54,11 @@ namespace log4net.Util
        /// <author>Nicko Cadell</author>
        public sealed class LogicalThreadContextProperties : 
ContextPropertiesBase
        {
+               #if NETSTANDARD1_3
+               private static readonly AsyncLocal<PropertiesDictionary> 
AsyncLocalDictionary = new AsyncLocal<PropertiesDictionary>();
+               #else
                private const string c_SlotName = 
"log4net.Util.LogicalThreadContextProperties";
+               #endif
                
                /// <summary>
                /// Flag used to disable this context if we don't have 
permission to access the CallContext.
@@ -105,7 +114,7 @@ namespace log4net.Util
                                // need to be immutable to correctly flow 
through async/await
                                PropertiesDictionary immutableProps = new 
PropertiesDictionary(props);
                                immutableProps[key] = value;
-                               SetCallContextData(immutableProps);
+                               SetLogicalProperties(immutableProps);
                        }
                }
 
@@ -129,7 +138,7 @@ namespace log4net.Util
                        {
                                PropertiesDictionary immutableProps = new 
PropertiesDictionary(dictionary);
                                immutableProps.Remove(key);
-                               SetCallContextData(immutableProps);
+                               SetLogicalProperties(immutableProps);
                        }
                }
 
@@ -147,7 +156,7 @@ namespace log4net.Util
                        if (dictionary != null)
                        {
                                PropertiesDictionary immutableProps = new 
PropertiesDictionary();
-                               SetCallContextData(immutableProps);
+                               SetLogicalProperties(immutableProps);
                        }
                }
 
@@ -173,11 +182,11 @@ namespace log4net.Util
                        {
                                try
                                {
-                                       PropertiesDictionary properties = 
GetCallContextData();
+                                       PropertiesDictionary properties = 
GetLogicalProperties();
                                        if (properties == null && create)
                                        {
                                                properties = new 
PropertiesDictionary();
-                                               SetCallContextData(properties);
+                                               
SetLogicalProperties(properties);
                                        }
                                        return properties;
                                }
@@ -214,9 +223,11 @@ namespace log4net.Util
 #if NET_4_0 || MONO_4_0
         [System.Security.SecuritySafeCritical]
 #endif
-        private static PropertiesDictionary GetCallContextData()
+        private static PropertiesDictionary GetLogicalProperties()
                {
-#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
+#if NETSTANDARD1_3
+            return AsyncLocalDictionary.Value;
+#elif NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
             return CallContext.LogicalGetData(c_SlotName) as 
PropertiesDictionary;
 #else
                        return CallContext.GetData(c_SlotName) as 
PropertiesDictionary;
@@ -235,9 +246,11 @@ namespace log4net.Util
 #if NET_4_0 || MONO_4_0
         [System.Security.SecuritySafeCritical]
 #endif
-        private static void SetCallContextData(PropertiesDictionary properties)
+        private static void SetLogicalProperties(PropertiesDictionary 
properties)
                {
-#if NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
+#if NETSTANDARD1_3
+                       AsyncLocalDictionary.Value = properties;
+#elif NET_2_0 || MONO_2_0 || MONO_3_5 || MONO_4_0
                        CallContext.LogicalSetData(c_SlotName, properties);
 #else
                        CallContext.SetData(c_SlotName, properties);

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/src/Util/PatternStringConverters/PropertyPatternConverter.cs
----------------------------------------------------------------------
diff --git a/src/Util/PatternStringConverters/PropertyPatternConverter.cs 
b/src/Util/PatternStringConverters/PropertyPatternConverter.cs
index 9c2051e..3124b31 100644
--- a/src/Util/PatternStringConverters/PropertyPatternConverter.cs
+++ b/src/Util/PatternStringConverters/PropertyPatternConverter.cs
@@ -68,7 +68,7 @@ namespace log4net.Util.PatternStringConverters
                {
                        CompositeProperties compositeProperties = new 
CompositeProperties();
 
-#if !(NETCF || NETSTANDARD1_3)
+#if !NETCF
                        PropertiesDictionary logicalThreadProperties = 
LogicalThreadContext.Properties.GetProperties(false);
                        if (logicalThreadProperties != null)
                        {

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/src/site/xdoc/release/framework-support.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/release/framework-support.xml 
b/src/site/xdoc/release/framework-support.xml
index 7cf2b34..f8e25b8 100644
--- a/src/site/xdoc/release/framework-support.xml
+++ b/src/site/xdoc/release/framework-support.xml
@@ -614,9 +614,6 @@ limitations under the License.
                       <li>anything related to ASP.NET (trace appender
                       and several pattern converters)</li>
                       <li>.NET Remoting</li>
-                      <li><code>log4net.LogicalThreadContext</code>
-                      and the associated properties and stack
-                      classes</li>
                       <li>the colored console appender</li>
                       <li>the event log appender</li>
                       <li>The <code>NetSendAppender</code></li>
@@ -630,6 +627,13 @@ limitations under the License.
                       <code>EnvironmentFolderPathPatternConverter</code></li>
                       <li>Impersonation of Windows accounts</li>
                     </ul>
+
+                    <p><code>log4net.LogicalThreadContext</code> and
+                    the associated properties and stack classes use
+                    <code>AsyncLocal</code> rather than
+                    <code>CallContext</code>. Prior to log4net 2.0.8
+                    they haven't been supported for .NET Standard at
+                    all.</p>
                 </section>
 
                 <section id="net1.0" name="Microsoft .NET Framework 1.0">

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/tests/src/Context/LogicalThreadContextTest.cs
----------------------------------------------------------------------
diff --git a/tests/src/Context/LogicalThreadContextTest.cs 
b/tests/src/Context/LogicalThreadContextTest.cs
index f3f0a19..849d963 100644
--- a/tests/src/Context/LogicalThreadContextTest.cs
+++ b/tests/src/Context/LogicalThreadContextTest.cs
@@ -17,7 +17,7 @@
 //
 #endregion
 
-#if NET_4_5
+#if NET_4_5 || NETSTANDARD1_3
 using System;
 using System.Threading.Tasks;
 using System.Linq;

http://git-wip-us.apache.org/repos/asf/logging-log4net/blob/201ad1ae/tests/src/Utils.cs
----------------------------------------------------------------------
diff --git a/tests/src/Utils.cs b/tests/src/Utils.cs
index 5cbfb9c..14e55d3 100644
--- a/tests/src/Utils.cs
+++ b/tests/src/Utils.cs
@@ -114,7 +114,7 @@ namespace log4net.Tests
         internal static void RemovePropertyFromAllContexts() {
             GlobalContext.Properties.Remove(PROPERTY_KEY);
             ThreadContext.Properties.Remove(PROPERTY_KEY);
-#if !(NETCF || NETSTANDARD1_3)
+#if !NETCF
             LogicalThreadContext.Properties.Remove(PROPERTY_KEY);
 #endif
         }

Reply via email to