1
0
mirror of https://github.com/DarthAffe/RGB.NET.git synced 2025-12-12 17:48:31 +00:00

Reduced allocations when a ListLedGroup is used

This commit is contained in:
Darth Affe 2023-04-13 00:21:20 +02:00
parent 764fcd1b1d
commit 0cf4f39ccf
5 changed files with 70 additions and 19 deletions

View File

@ -1,4 +1,5 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@ -61,5 +62,14 @@ public abstract class AbstractLedGroup : AbstractDecoratable<ILedGroupDecorator>
/// <inheritdoc />
public IEnumerator<Led> GetEnumerator() => GetLeds().GetEnumerator();
/// <inheritdoc />
IDisposable? ILedGroup.ToListUnsafe(out IList<Led> leds) => ToListUnsafe(out leds);
protected virtual IDisposable? ToListUnsafe(out IList<Led> leds)
{
leds = ToList();
return null;
}
#endregion
}

View File

@ -1,6 +1,7 @@
// ReSharper disable UnusedMemberInSuper.Global
// ReSharper disable UnusedMember.Global
using System;
using System.Collections.Generic;
namespace RGB.NET.Core;
@ -45,4 +46,6 @@ public interface ILedGroup : IDecoratable<ILedGroupDecorator>, IEnumerable<Led>
/// </summary>
/// <returns>A list containing all <see cref="Led"/> in this group.</returns>
IList<Led> ToList();
internal IDisposable? ToListUnsafe(out IList<Led> leds);
}

View File

@ -1,7 +1,9 @@
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedMember.Global
using System;
using System.Collections.Generic;
using System.Threading;
namespace RGB.NET.Core;
@ -135,5 +137,12 @@ public class ListLedGroup : AbstractLedGroup
return new List<Led>(GroupLeds);
}
protected override IDisposable ToListUnsafe(out IList<Led> leds)
{
Monitor.Enter(GroupLeds);
leds = GroupLeds;
return new ActionDisposable(() => Monitor.Exit(GroupLeds));
}
#endregion
}

View File

@ -0,0 +1,27 @@
using System;
namespace RGB.NET.Core;
public sealed class ActionDisposable : IDisposable
{
#region Properties & Fields
private readonly Action _onDispose;
#endregion
#region Constructors
public ActionDisposable(Action onDispose)
{
this._onDispose = onDispose;
}
#endregion
#region Methods
public void Dispose() => _onDispose();
#endregion
}

View File

@ -208,26 +208,28 @@ public sealed class RGBSurface : AbstractBindable, IDisposable
if ((brush == null) || !brush.IsEnabled) return;
IList<Led> leds = ledGroup.ToList();
IEnumerable<(RenderTarget renderTarget, Color color)> render;
switch (brush.CalculationMode)
using (ledGroup.ToListUnsafe(out IList<Led> leds))
{
case RenderMode.Relative:
Rectangle brushRectangle = new(leds);
Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y);
brushRectangle = brushRectangle.SetLocation(new Point(0, 0));
render = brush.Render(brushRectangle, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary.Translate(offset))));
break;
case RenderMode.Absolute:
render = brush.Render(Boundary, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary)));
break;
default:
throw new ArgumentException($"The CalculationMode '{brush.CalculationMode}' is not valid.");
}
IEnumerable<(RenderTarget renderTarget, Color color)> render;
switch (brush.CalculationMode)
{
case RenderMode.Relative:
Rectangle brushRectangle = new(leds);
Point offset = new(-brushRectangle.Location.X, -brushRectangle.Location.Y);
brushRectangle = brushRectangle.SetLocation(new Point(0, 0));
render = brush.Render(brushRectangle,
leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary.Translate(offset))));
break;
case RenderMode.Absolute:
render = brush.Render(Boundary, leds.Select(led => new RenderTarget(led, led.AbsoluteBoundary)));
break;
default:
throw new ArgumentException($"The CalculationMode '{brush.CalculationMode}' is not valid.");
}
foreach ((RenderTarget renderTarget, Color c) in render)
renderTarget.Led.Color = c;
foreach ((RenderTarget renderTarget, Color c) in render)
renderTarget.Led.Color = c;
}
}
/// <summary>