Skip to content

Commit

Permalink
Change locks to System.Threading.Lock (#11841)
Browse files Browse the repository at this point in the history
Change internal lock objects to System.Threading.Lock

Fixes #11672
  • Loading branch information
JeremyKuhne authored Aug 8, 2024
1 parent 6e7755c commit de9af8f
Show file tree
Hide file tree
Showing 24 changed files with 90 additions and 115 deletions.
4 changes: 4 additions & 0 deletions src/System.Drawing.Common/src/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
global using Windows.Win32.System.Memory;
global using Windows.Win32.UI.WindowsAndMessaging;

#if NET9_0_OR_GREATER
global using Lock = System.Threading.Lock;
#endif

global using BitmapData = System.Drawing.Imaging.BitmapData;
global using ColorPalette = System.Drawing.Imaging.ColorPalette;
global using DashCap = System.Drawing.Drawing2D.DashCap;
Expand Down
2 changes: 1 addition & 1 deletion src/System.Drawing.Common/src/System/Drawing/Graphics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public sealed unsafe partial class Graphics : MarshalByRefObject, IDisposable, I
/// </summary>
private GraphicsContext? _previousContext;

private static readonly object s_syncObject = new();
private static readonly Lock s_syncObject = new();

// Object reference used for printing; it could point to a PrintPreviewGraphics to obtain the VisibleClipBounds, or
// a DeviceContext holding a printer DC.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal static class SystemColorTracker
private static WeakReference<ISystemColorTracker>?[] s_list = new WeakReference<ISystemColorTracker>?[INITIAL_SIZE];
private static int s_count;
private static bool s_addedTracker;
private static readonly object s_lockObject = new();
private static readonly Lock s_lockObject = new();

internal static void Add(ISystemColorTracker obj)
{
Expand Down
11 changes: 11 additions & 0 deletions src/System.Drawing.Common/src/System/Drawing/Lock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Drawing;

#if !NET9_0_OR_GREATER
// System.Threading.Lock stub for NET8.0 and below
internal class Lock
{
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class MenuCommandService : IMenuCommandService, IDisposable
{
private IServiceProvider? _serviceProvider;
private readonly Dictionary<Guid, List<MenuCommand>> _commandGroups;
private readonly object _commandGroupsLock;
private readonly Lock _commandGroupsLock = new();
private readonly EventHandler _commandChangedHandler;
private MenuCommandsChangedEventHandler? _commandsChangedHandler;
private List<DesignerVerb>? _globalVerbs;
Expand All @@ -38,7 +38,6 @@ public class MenuCommandService : IMenuCommandService, IDisposable
public MenuCommandService(IServiceProvider? serviceProvider)
{
_serviceProvider = serviceProvider;
_commandGroupsLock = new object();
_commandGroups = [];
_commandChangedHandler = new EventHandler(OnCommandChanged);
TypeDescriptor.Refreshed += new RefreshEventHandler(OnTypeRefreshed);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public sealed class NoAssertContext : IDisposable
// We do, however need to lock around hooking/unhooking our custom listener to make sure that we
// are rerouting correctly if multiple threads are creating/disposing this class concurrently.

private static readonly object s_lock = new();
private static readonly Lock s_lock = new();
private static bool s_hooked;
private static bool s_hasDefaultListener;
private static bool s_hasThrowingListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ internal abstract unsafe partial class ThreadContext : MarshalByRefObject, IHand

private static readonly Dictionary<uint, ThreadContext> s_contextHash = [];

// When this gets to zero, we'll invoke a full garbage
// collect and check for root/window leaks.
private static readonly object s_tcInternalSyncObject = new();
private static readonly Lock s_tcInternalSyncObject = new();

private static int s_totalMessageLoopCount;
private static msoloop s_baseLoopReason;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public sealed partial class Application
private static bool s_comCtlSupportsVisualStylesInitialized;
private static bool s_comCtlSupportsVisualStyles;
private static FormCollection? s_forms;
private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();
private static bool s_useWaitCursor;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ private class ThreadMethodEntry : IAsyncResult
internal Exception? _exception;
internal bool _synchronous;
private ManualResetEvent? _resetEvent;
private readonly object _invokeSyncObject = new();
private readonly Lock _invokeSyncObject = new();

// Store the execution context associated with the caller thread, and
// information about which thread actually got the stack applied to it.
Expand All @@ -44,33 +44,21 @@ internal ThreadMethodEntry(
_executionContext = executionContext;
}

public object? AsyncState
{
get
{
return null;
}
}
public object? AsyncState => null;

public WaitHandle AsyncWaitHandle
{
get
{
if (_resetEvent is null)
{
// Locking 'this' here is ok since this is an internal class.
lock (_invokeSyncObject)
{
// BeginInvoke hangs on Multi-proc system:
// taking the lock prevents a race condition between IsCompleted
// boolean flag and resetEvent mutex in multiproc scenarios.
if (_resetEvent is null)
_resetEvent ??= new ManualResetEvent(false);

if (IsCompleted)
{
_resetEvent = new ManualResetEvent(false);
if (IsCompleted)
{
_resetEvent.Set();
}
_resetEvent.Set();
}
}
}
Expand All @@ -79,18 +67,7 @@ public WaitHandle AsyncWaitHandle
}
}

public bool CompletedSynchronously
{
get
{
if (IsCompleted && _synchronous)
{
return true;
}

return false;
}
}
public bool CompletedSynchronously => IsCompleted && _synchronous;

public bool IsCompleted { get; private set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal sealed class NativeImageList : IDisposable, IHandle<HIMAGELIST>
private const int GrowBy = 4;
private const int InitialCapacity = 4;

private static readonly object s_syncLock = new();
private static readonly Lock s_syncLock = new();

public unsafe NativeImageList(IStream.Interface pstm)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class ImageListStreamer : ISerializable, IDisposable
{
// Compressed magic header. If we see this, the image stream is compressed.
private static ReadOnlySpan<byte> HeaderMagic => "MSFt"u8;
private static readonly object s_syncObject = new();
private static readonly Lock s_syncObject = new();

private readonly ImageList? _imageList;
private ImageList.NativeImageList? _nativeImageList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public partial class PictureBox : Control, ISupportInitialize
private SendOrPostCallback? _loadCompletedDelegate;
private SendOrPostCallback? _loadProgressDelegate;
private bool _handleValid;
private readonly object _internalSyncObject = new();
private readonly Lock _internalSyncObject = new();

// These default images will be demand loaded.
private Image? _defaultInitialImage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public static partial class ToolStripManager
private const int StaticEventDefaultRendererChanged = 0;
private const int StaticEventCount = 1;

private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();

private static void InitializeThread()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal class Command : WeakReference
{
private static Command?[]? s_cmds;
private static int s_icmdTry;
private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();
private const int IdMin = 0x00100;
private const int IdLim = 0x10000;

Expand All @@ -19,13 +19,7 @@ public Command(ICommandExecutor target)
AssignID(this);
}

public virtual int ID
{
get
{
return _id;
}
}
public virtual int ID => _id;

protected static void AssignID(Command cmd)
{
Expand Down
25 changes: 5 additions & 20 deletions src/System.Windows.Forms/src/System/Windows/Forms/Form.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public partial class Form : ContainerControl
private const int SizeGripSize = 16;

private static Icon? s_defaultIcon;
private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();

// Property store keys for properties. The property store allocates most efficiently
// in groups of four, so we try to lump properties in groups of four based on how
Expand Down Expand Up @@ -886,13 +886,12 @@ internal static Icon DefaultIcon
{
get
{
// Avoid locking if the value is filled in...
// Avoid locking if the value is filled in.
if (s_defaultIcon is null)
{
lock (s_internalSyncObject)
{
// Once we grab the lock, we re-check the value to avoid a
// race condition.
// Once we grab the lock, we re-check the value to avoid a race condition.
s_defaultIcon ??= new Icon(typeof(Form), "wfc");
}
}
Expand All @@ -901,25 +900,13 @@ internal static Icon DefaultIcon
}
}

protected override ImeMode DefaultImeMode
{
get
{
return ImeMode.NoControl;
}
}
protected override ImeMode DefaultImeMode => ImeMode.NoControl;

/// <summary>
/// Deriving classes can override this to configure a default size for their control.
/// This is more efficient than setting the size in the control's constructor.
/// </summary>
protected override Size DefaultSize
{
get
{
return new Size(300, 300);
}
}
protected override Size DefaultSize => new Size(300, 300);

/// <summary>
/// Gets or sets the size and location of the form on the Windows desktop.
Expand All @@ -938,7 +925,6 @@ public Rectangle DesktopBounds
bounds.Y -= screen.Y;
return bounds;
}

set
{
SetDesktopBounds(value.X, value.Y, value.Width, value.Height);
Expand All @@ -962,7 +948,6 @@ public Point DesktopLocation
loc.Y -= screen.Y;
return loc;
}

set
{
SetDesktopLocation(value.X, value.Y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public unsafe partial class NativeWindow : MarshalByRefObject, IWin32Window, IHa
private static short s_globalID = 1;
private static readonly Dictionary<HWND, GCHandle> s_windowHandles = [];
private static readonly Dictionary<short, HWND> s_windowIds = [];
private static readonly object s_internalSyncObject = new();
private static readonly object s_createWindowSyncObject = new();
private static readonly Lock s_internalSyncObject = new();
private static readonly Lock s_createWindowSyncObject = new();

// Our window procedure delegate
private WNDPROC? _windowProc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public sealed partial class NotifyIcon : Component
private const int WM_TRAYMOUSEMESSAGE = (int)PInvoke.WM_USER + 1024;
private static uint WM_TASKBARCREATED { get; } = PInvoke.RegisterWindowMessage("TaskbarCreated");

private readonly object _syncObj = new();
private readonly Lock _lock = new();

private Icon? _icon;
private string _text = string.Empty;
Expand Down Expand Up @@ -623,7 +623,7 @@ private void ShowContextMenu()
/// </summary>
private unsafe void UpdateIcon(bool showIconInTray)
{
lock (_syncObj)
lock (_lock)
{
// Bail if in design mode...
if (DesignMode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public static partial class DataFormats
private static Format[]? s_formatList;
private static int s_formatCount;

private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();

/// <summary>
/// Gets a <see cref="Format"/> with the Windows Clipboard numeric ID and name for the specified format.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace System.Windows.Forms;
public class OwnerDrawPropertyBag : MarshalByRefObject, ISerializable
{
private Control.FontHandleWrapper? _fontWrapper;
private static readonly object s_internalSyncObject = new();
private static readonly Lock s_internalSyncObject = new();

protected OwnerDrawPropertyBag(SerializationInfo info, StreamingContext context)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace System.Windows.Forms;
/// </remarks>
internal sealed partial class FontCache : RefCountedCache<HFONT, FontCache.Data, (Font Font, FONT_QUALITY Quality)>
{
private readonly object _lock = new();
private readonly Lock _lock = new();

/// <summary>
/// Create a <see cref="FontCache"/> with the specified collection limits.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public partial class Screen

private readonly int _bitDepth;

private static readonly object s_syncLock = new(); // used to lock this class before syncing to SystemEvents
private static readonly Lock s_syncLock = new(); // used to lock this class before syncing to SystemEvents

private static int s_desktopChangedCount = -1; // static counter of desktop size changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public partial class SendKeys
/// </summary>
private static readonly Queue<SKEvent> s_events = new();

private static readonly object s_lock = new();
private static readonly Lock s_lock = new();
private static bool s_startNewChar;
private static readonly SKWindow s_messageWindow;

Expand Down
Loading

0 comments on commit de9af8f

Please sign in to comment.