Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,24 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Threading;

namespace Interop.Windows.Sni
{
internal unsafe class SqlDependencyProcessDispatcherStorage
internal class SqlDependencyProcessDispatcherStorage
{
private static void* s_data;
private static readonly object s_lockObj = new();
private static IntPtr s_data;
private static int s_size;
private static volatile int s_lock; // Int used for a spin-lock.

[ResourceExposure(ResourceScope.Process)] // SxS: there is no way to set scope = Instance, using Process which is wider
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
public static byte[] NativeGetData()
{
IntPtr ptr = (IntPtr)s_data;

byte[] result = null;
if (ptr != IntPtr.Zero)
if (s_data != IntPtr.Zero)
{
result = new byte[s_size];
Marshal.Copy(ptr, result, 0, s_size);
Marshal.Copy(s_data, result, 0, s_size);
}

return result;
Expand All @@ -38,29 +35,18 @@ public static byte[] NativeGetData()
[ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
internal static void NativeSetData(byte[] data)
{
fixed (byte* pDispatcher = data)
lock (s_lockObj)
{
while (Interlocked.CompareExchange(ref s_lock, 1, 0) != 0)
if (s_data == IntPtr.Zero)
{
// Spin until we have the lock.
Thread.Sleep(50); // Sleep with short-timeout to prevent starvation.
}
Trace.Assert(s_lock == 1); // Now that we have the lock, lock should be equal to 1.

if (s_data == null)
{
s_data = Marshal.AllocHGlobal(data.Length).ToPointer();

Trace.Assert(s_data != null);

Buffer.MemoryCopy(pDispatcher, s_data, data.Length, data.Length);

Trace.Assert(0 == s_size); // Size should still be zero at this point.
s_data = Marshal.AllocHGlobal(data.Length);
Trace.Assert(s_data != IntPtr.Zero);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this Assert() is helpful. AllocHGlobal() either allocates memory successfully and returns an IntPtr to it, or it throws. Granted, the AllocHGlobal() docs don't explicitly say the returned IntPtr.Zero will never be true, but so what if it is? Will Copy() work if s_data.Zero is true? Those docs don't say either way, so I'm not sure we should be making any assumptions here. I think this Assert() gives a false sense of program state below (i.e. s_data.Zero == false). If it's important that we never call Copy() with a Zero IntPtr, then we need an if-statement.

This is just FYI - no need to make any changes - just wanted to point it out.


Marshal.Copy(data, 0, s_data, data.Length);

Trace.Assert(s_size == 0); // Size should still be zero at this point
s_size = data.Length;
}

int result = Interlocked.CompareExchange(ref s_lock, 0, 1);
Trace.Assert(1 == result); // The release of the lock should have been successful.
}
}
}
Expand Down
Loading