[DtrBar] Probably fix concurrency issues

This commit is contained in:
MidoriKami 2023-09-05 14:03:37 -07:00
parent 153f7c45bf
commit 166669597d

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -50,6 +51,7 @@ public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
private readonly DalamudAddonEventManager uiEventManager = Service<DalamudAddonEventManager>.Get(); private readonly DalamudAddonEventManager uiEventManager = Service<DalamudAddonEventManager>.Get();
private readonly DtrBarAddressResolver address; private readonly DtrBarAddressResolver address;
private readonly ConcurrentBag<DtrBarEntry> newEntries = new();
private readonly List<DtrBarEntry> entries = new(); private readonly List<DtrBarEntry> entries = new();
private readonly Hook<AddonDrawDelegate> onAddonDrawHook; private readonly Hook<AddonDrawDelegate> onAddonDrawHook;
private readonly Hook<AddonRequestedUpdateDelegate> onAddonRequestedUpdateHook; private readonly Hook<AddonRequestedUpdateDelegate> onAddonRequestedUpdateHook;
@ -78,18 +80,17 @@ public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
/// <inheritdoc/> /// <inheritdoc/>
public DtrBarEntry Get(string title, SeString? text = null) public DtrBarEntry Get(string title, SeString? text = null)
{ {
if (this.entries.Any(x => x.Title == title)) if (this.entries.Any(x => x.Title == title) || this.newEntries.Any(x => x.Title == title))
throw new ArgumentException("An entry with the same title already exists."); throw new ArgumentException("An entry with the same title already exists.");
var node = this.MakeNode(++this.runningNodeIds); var entry = new DtrBarEntry(title, null);
var entry = new DtrBarEntry(title, node);
entry.Text = text; entry.Text = text;
// Add the entry to the end of the order list, if it's not there already. // Add the entry to the end of the order list, if it's not there already.
if (!this.configuration.DtrOrder!.Contains(title)) if (!this.configuration.DtrOrder!.Contains(title))
this.configuration.DtrOrder!.Add(title); this.configuration.DtrOrder!.Add(title);
this.entries.Add(entry);
this.ApplySort(); this.newEntries.Add(entry);
return entry; return entry;
} }
@ -173,6 +174,7 @@ public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
private void Update(Framework unused) private void Update(Framework unused)
{ {
this.HandleRemovedNodes(); this.HandleRemovedNodes();
this.HandleAddedNodes();
var dtr = this.GetDtr(); var dtr = this.GetDtr();
if (dtr == null) return; if (dtr == null) return;
@ -238,6 +240,21 @@ public sealed unsafe class DtrBar : IDisposable, IServiceType, IDtrBar
} }
} }
private void HandleAddedNodes()
{
if (this.newEntries.Any())
{
foreach (var newEntry in this.newEntries)
{
newEntry.TextNode = this.MakeNode(++this.runningNodeIds);
this.entries.Add(newEntry);
}
this.newEntries.Clear();
this.ApplySort();
}
}
// This hooks all AtkUnitBase.Draw calls, then checks for our specific addon name. // This hooks all AtkUnitBase.Draw calls, then checks for our specific addon name.
// AddonDtr doesn't implement it's own Draw method, would need to replace vtable entry to be more efficient. // AddonDtr doesn't implement it's own Draw method, would need to replace vtable entry to be more efficient.
private void OnAddonDrawDetour(AtkUnitBase* addon) private void OnAddonDrawDetour(AtkUnitBase* addon)