Improved handling of critical sections to solve deadlocks.

This commit is contained in:
IceStormNG
2023-07-27 10:13:24 +02:00
parent a9c104d388
commit ef31935b24

View File

@@ -1,21 +1,28 @@
using GHelper.Peripherals.Mouse; using GHelper.Peripherals.Mouse;
using GHelper.Peripherals.Mouse.Models; using GHelper.Peripherals.Mouse.Models;
using System.Runtime.CompilerServices;
namespace GHelper.Peripherals namespace GHelper.Peripherals
{ {
public class PeripheralsProvider public class PeripheralsProvider
{ {
public static object _LOCK = new object(); private static readonly object _LOCK = new object();
public static List<AsusMouse> ConnectedMice = new List<AsusMouse>(); public static List<AsusMouse> ConnectedMice = new List<AsusMouse>();
public static event EventHandler? DeviceChanged; public static event EventHandler? DeviceChanged;
public static bool IsMouseConnected() public static bool IsMouseConnected()
{
lock (_LOCK)
{ {
return ConnectedMice.Count > 0; return ConnectedMice.Count > 0;
} }
}
public static bool IsDeviceConnected(IPeripheral peripheral)
{
return AllPeripherals().Contains(peripheral);
}
//Expand if keyboards or other device get supported later. //Expand if keyboards or other device get supported later.
public static bool IsAnyPeripheralConnect() public static bool IsAnyPeripheralConnect()
@@ -26,18 +33,18 @@ namespace GHelper.Peripherals
public static List<IPeripheral> AllPeripherals() public static List<IPeripheral> AllPeripherals()
{ {
List<IPeripheral> l = new List<IPeripheral>(); List<IPeripheral> l = new List<IPeripheral>();
lock (_LOCK)
{
l.AddRange(ConnectedMice); l.AddRange(ConnectedMice);
}
return l; return l;
} }
public static void RefreshBatteryForAllDevices() public static void RefreshBatteryForAllDevices()
{ {
if (!IsAnyPeripheralConnect()) return; List<IPeripheral> l = AllPeripherals();
lock (_LOCK) foreach (IPeripheral m in l)
{
foreach (IPeripheral m in AllPeripherals())
{ {
if (!m.IsDeviceReady) if (!m.IsDeviceReady)
{ {
@@ -51,29 +58,27 @@ namespace GHelper.Peripherals
} }
} }
}
public static void Disconnect(AsusMouse am) public static void Disconnect(AsusMouse am)
{ {
lock (_LOCK) lock (_LOCK)
{ {
ConnectedMice.Remove(am); ConnectedMice.Remove(am);
}
if (DeviceChanged is not null) if (DeviceChanged is not null)
{ {
DeviceChanged(am, EventArgs.Empty); DeviceChanged(am, EventArgs.Empty);
} }
} }
}
public static void Connect(AsusMouse am) public static void Connect(AsusMouse am)
{ {
lock (_LOCK)
{ if (IsDeviceConnected(am))
if (ConnectedMice.Contains(am))
{ {
//Mouse already connected; //Mouse already connected;
return; return;
} }
try try
{ {
am.Connect(); am.Connect();
@@ -84,8 +89,6 @@ namespace GHelper.Peripherals
return; return;
} }
am.Disconnect += Mouse_Disconnect;
//The Mouse might needs a few ms to register all its subdevices or the sync will fail. //The Mouse might needs a few ms to register all its subdevices or the sync will fail.
//Retry 3 times. Do not call this on main thread! It would block the UI //Retry 3 times. Do not call this on main thread! It would block the UI
@@ -98,15 +101,20 @@ namespace GHelper.Peripherals
++tries; ++tries;
} }
lock (_LOCK)
{
ConnectedMice.Add(am); ConnectedMice.Add(am);
}
Logger.WriteLine(am.GetDisplayName() + " added to the list: " + ConnectedMice.Count + " device are conneted."); Logger.WriteLine(am.GetDisplayName() + " added to the list: " + ConnectedMice.Count + " device are conneted.");
am.Disconnect += Mouse_Disconnect;
if (DeviceChanged is not null) if (DeviceChanged is not null)
{ {
DeviceChanged(am, EventArgs.Empty); DeviceChanged(am, EventArgs.Empty);
} }
UpdateSettingsView(); UpdateSettingsView();
} }
}
private static void Mouse_Disconnect(object? sender, EventArgs e) private static void Mouse_Disconnect(object? sender, EventArgs e)
{ {
@@ -114,15 +122,18 @@ namespace GHelper.Peripherals
{ {
return; return;
} }
AsusMouse am = (AsusMouse)sender;
lock (_LOCK) lock (_LOCK)
{ {
AsusMouse am = (AsusMouse)sender;
ConnectedMice.Remove(am); ConnectedMice.Remove(am);
}
Logger.WriteLine(am.GetDisplayName() + " reported disconnect. " + ConnectedMice.Count + " device are conneted."); Logger.WriteLine(am.GetDisplayName() + " reported disconnect. " + ConnectedMice.Count + " device are conneted.");
am.Dispose(); am.Dispose();
UpdateSettingsView(); UpdateSettingsView();
} }
}
private static void UpdateSettingsView() private static void UpdateSettingsView()
@@ -141,12 +152,11 @@ namespace GHelper.Peripherals
DetectMouse(new ChakramXWired()); DetectMouse(new ChakramXWired());
DetectMouse(new GladiusIII()); DetectMouse(new GladiusIII());
DetectMouse(new GladiusIIIWired()); DetectMouse(new GladiusIIIWired());
UpdateSettingsView();
} }
public static void DetectMouse(AsusMouse am) public static void DetectMouse(AsusMouse am)
{ {
if (am.IsDeviceConnected() && !ConnectedMice.Contains(am)) if (am.IsDeviceConnected() && !IsDeviceConnected(am))
{ {
Logger.WriteLine("Detected a new" + am.GetDisplayName() + " . Connecting..."); Logger.WriteLine("Detected a new" + am.GetDisplayName() + " . Connecting...");
Connect(am); Connect(am);