From b47b92b5e3229ae0952804b51e2adc19320768f6 Mon Sep 17 00:00:00 2001 From: Gartia Date: Sun, 28 Apr 2024 00:05:19 -0700 Subject: [PATCH] Refactor: Replace ThreadStatic with ThreadLocal for Improved Thread Safety The existing use of `ThreadStatic` for `staticBuffer` effectively makes it a global static variable across all threads, with initialization in the static constructor. This approach can lead to issues where multiple threads overwrite each other's data, as each thread does not get its own instance of the buffer. `ThreadLocal`, on the other hand, ensures that each thread gets its own instance of the buffer, initialized independently. This change will enhance the reliability of serialization when `ProtocolParser` is used concurrently across multiple threads. Using this method you are required to use staticBuffer.Value though if any of the non public code is using staticBuffer it will need to be changed. --- .../ProtocolParser/ProtocolParser.cs | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/CodeGenerator/ProtocolParser/ProtocolParser.cs b/CodeGenerator/ProtocolParser/ProtocolParser.cs index fabe00b..9a44fa3 100644 --- a/CodeGenerator/ProtocolParser/ProtocolParser.cs +++ b/CodeGenerator/ProtocolParser/ProtocolParser.cs @@ -17,9 +17,8 @@ public interface IProto public static partial class ProtocolParser { - // Seperate copy of buffer per thread - [ThreadStatic] - private static byte[] staticBuffer = new byte[ 1024 * 128 ]; + // Thread static does not support intializers use threadlocal and access using staticBuffer.Value + private static ThreadLocal staticBuffer = new ThreadLocal(() => new byte[ 1024 * 128 ]); public static float ReadSingle( Stream stream ) { @@ -28,8 +27,8 @@ public static float ReadSingle( Stream stream ) return reader.Float(); } - stream.Read( staticBuffer, 0, 4 ); - return staticBuffer.ReadUnsafe(); + stream.Read( staticBuffer.Value, 0, 4 ); + return staticBuffer.Value.ReadUnsafe(); } public static void WriteSingle( Stream stream, float f ) @@ -40,8 +39,8 @@ public static void WriteSingle( Stream stream, float f ) return; } - staticBuffer.WriteUnsafe( f ); - stream.Write( staticBuffer, 0, 4 ); + staticBuffer.Value.WriteUnsafe( f ); + stream.Write( staticBuffer.Value, 0, 4 ); } public static double ReadDouble( Stream stream ) @@ -51,8 +50,8 @@ public static double ReadDouble( Stream stream ) return reader.Double(); } - stream.Read( staticBuffer, 0, 8 ); - return staticBuffer.ReadUnsafe(); + stream.Read( staticBuffer.Value, 0, 8 ); + return staticBuffer.Value.ReadUnsafe(); } public static void WriteDouble( Stream stream, double f ) @@ -63,8 +62,8 @@ public static void WriteDouble( Stream stream, double f ) return; } - staticBuffer.WriteUnsafe( f ); - stream.Write( staticBuffer, 0, 8 ); + staticBuffer.Value.WriteUnsafe( f ); + stream.Write( staticBuffer.Value, 0, 8 ); } public static string ReadString( Stream stream ) @@ -81,7 +80,7 @@ public static string ReadString( Stream stream ) string str; - if (length >= staticBuffer.Length) + if (length >= staticBuffer.Value.Length) { Profiler.BeginSample( "new Buffer" ); byte[] buffer = new byte[ length ]; @@ -91,8 +90,8 @@ public static string ReadString( Stream stream ) } else { - stream.Read( staticBuffer, 0, length ); - str = Encoding.UTF8.GetString( staticBuffer, 0, length ); + stream.Read( staticBuffer.Value, 0, length ); + str = Encoding.UTF8.GetString( staticBuffer.Value, 0, length ); } Profiler.EndSample(); @@ -109,10 +108,10 @@ public static void WriteString( Stream stream, string val ) } Profiler.BeginSample( "ProtoParser.WriteString" ); - var len = Encoding.UTF8.GetBytes( val, 0, val.Length, staticBuffer, 0 ); + var len = Encoding.UTF8.GetBytes( val, 0, val.Length, staticBuffer.Value, 0 ); WriteUInt32( stream, (uint)len ); - stream.Write( staticBuffer, 0, len ); + stream.Write( staticBuffer.Value, 0, len ); Profiler.EndSample(); } @@ -212,4 +211,4 @@ public static void WritePooledBytes( Stream stream, ArraySegment segment ) stream.Write( segment.Array, segment.Offset, segment.Count ); } } -} \ No newline at end of file +}