mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-14 04:34:16 +01:00
Better unload
This commit is contained in:
parent
b8724f7a59
commit
c51e65e0bd
2 changed files with 14 additions and 34 deletions
|
|
@ -19,13 +19,13 @@ namespace Dalamud.Game.Addon.Lifecycle;
|
||||||
[ServiceManager.EarlyLoadedService]
|
[ServiceManager.EarlyLoadedService]
|
||||||
internal unsafe class AddonLifecycle : IInternalDisposableService
|
internal unsafe class AddonLifecycle : IInternalDisposableService
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of all allocated addon virtual tables.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly List<AddonVirtualTable> AllocatedTables = [];
|
||||||
|
|
||||||
private static readonly ModuleLog Log = new("AddonLifecycle");
|
private static readonly ModuleLog Log = new("AddonLifecycle");
|
||||||
|
|
||||||
[ServiceManager.ServiceDependency]
|
|
||||||
private readonly Framework framework = Service<Framework>.Get();
|
|
||||||
|
|
||||||
private readonly Dictionary<string, AddonVirtualTable> modifiedTables = [];
|
|
||||||
|
|
||||||
private Hook<AtkUnitBase.Delegates.Initialize>? onInitializeAddonHook;
|
private Hook<AtkUnitBase.Delegates.Initialize>? onInitializeAddonHook;
|
||||||
|
|
||||||
[ServiceManager.ServiceConstructor]
|
[ServiceManager.ServiceConstructor]
|
||||||
|
|
@ -47,13 +47,8 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
||||||
this.onInitializeAddonHook?.Dispose();
|
this.onInitializeAddonHook?.Dispose();
|
||||||
this.onInitializeAddonHook = null;
|
this.onInitializeAddonHook = null;
|
||||||
|
|
||||||
this.framework.RunOnFrameworkThread(() =>
|
AllocatedTables.ForEach(entry => entry.Dispose());
|
||||||
{
|
AllocatedTables.Clear();
|
||||||
foreach (var virtualTable in this.modifiedTables.Values)
|
|
||||||
{
|
|
||||||
virtualTable.Dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -141,18 +136,8 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
||||||
{
|
{
|
||||||
this.LogInitialize(addon->NameString);
|
this.LogInitialize(addon->NameString);
|
||||||
|
|
||||||
if (!this.modifiedTables.ContainsKey(addon->NameString))
|
// AddonVirtualTable class handles creating the virtual table, and overriding each of the tracked virtual functions
|
||||||
{
|
AllocatedTables.Add(new AddonVirtualTable(addon, this));
|
||||||
// AddonVirtualTable class handles creating the virtual table, and overriding each of the tracked virtual functions
|
|
||||||
var managedVirtualTableEntry = new AddonVirtualTable(addon, this)
|
|
||||||
{
|
|
||||||
// This event is invoked when the game itself has disposed of an addon
|
|
||||||
// We can use this to know when to remove our virtual table entry
|
|
||||||
OnAddonFinalized = () => this.modifiedTables.Remove(addon->NameString),
|
|
||||||
};
|
|
||||||
|
|
||||||
this.modifiedTables.Add(addon->NameString, managedVirtualTableEntry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
|
||||||
using Dalamud.Logging.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
|
|
@ -108,17 +109,11 @@ internal unsafe class AddonVirtualTable : IDisposable
|
||||||
this.modifiedVirtualTable->Hide = (delegate* unmanaged<AtkUnitBase*, bool, bool, uint, void>)Marshal.GetFunctionPointerForDelegate(this.hideFunction);
|
this.modifiedVirtualTable->Hide = (delegate* unmanaged<AtkUnitBase*, bool, bool, uint, void>)Marshal.GetFunctionPointerForDelegate(this.hideFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Gets an event that is invoked when this addon's Finalize method is called from native.
|
|
||||||
/// </summary>
|
|
||||||
public required Action OnAddonFinalized { get; init; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <em>WARNING!</em> This should not be called at any time except during dalamud unload.
|
|
||||||
/// </summary>
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
this.atkUnitBase->VirtualTable = this.originalVirtualTable;
|
// Ensure restoration is done atomically.
|
||||||
|
Interlocked.Exchange(ref *(nint*)&this.atkUnitBase->VirtualTable, (nint)this.originalVirtualTable);
|
||||||
IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount);
|
IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,7 +126,7 @@ internal unsafe class AddonVirtualTable : IDisposable
|
||||||
if ((freeFlags & 1) == 1)
|
if ((freeFlags & 1) == 1)
|
||||||
{
|
{
|
||||||
IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount);
|
IMemorySpace.Free(this.modifiedVirtualTable, 0x8 * VirtualTableEntryCount);
|
||||||
this.OnAddonFinalized();
|
AddonLifecycle.AllocatedTables.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue