mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-16 21:07:43 +01:00
Add IInternal/PublicDisposableService (#1696)
* Add IInternal/PublicDisposableService Plugins are exposed interfaces that are not inherited from `IDisposable`, but services implementing plugin interfaces often implement `IDisposable`. Some plugins may try to call `IDisposable.Dispose` on everything provided, and it also is possible to use `using` clause too eagerly while working on Dalamud itself, such as writing `using var smth = await Service<SomeService>.GetAsync();`. Such behaviors often lead to a difficult-to-debug errors, and making those services either not an `IDisposable` or making `IDisposable.Dispose` do nothing if the object has been loaded would prevent such errors. As `ServiceManager` must be the only class dealing with construction and disposal of services, `IInternalDisposableService` has been added to limit who can dispose the object. `IPublicDisposableService` also has been added to classes that can be constructed and accessed directly by plugins; for those, `Dispose` will be ignored if the instance is a service instance, and only `DisposeService` will respond. In addition, `DalamudPluginInterface` and `UiBuilder` also have been changed so that their `IDisposable.Dispose` no longer respond, and instead, internal functions have been added to only allow disposal from Dalamud. * Cleanup * Postmerge fixes * More explanation on RunOnFrameworkThread(ClearHooks) * Mark ReliableFileStorage public ctor obsolete --------- Co-authored-by: goat <16760685+goaaats@users.noreply.github.com>
This commit is contained in:
parent
dcec076ca7
commit
87b9edb448
62 changed files with 441 additions and 381 deletions
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Storage.Assets;
|
|||
#pragma warning disable SA1015
|
||||
[ResolveVia<IDalamudAssetManager>]
|
||||
#pragma warning restore SA1015
|
||||
internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudAssetManager
|
||||
internal sealed class DalamudAssetManager : IInternalDisposableService, IDalamudAssetManager
|
||||
{
|
||||
private const int DownloadAttemptCount = 10;
|
||||
private const int RenameAttemptCount = 10;
|
||||
|
|
@ -67,7 +67,13 @@ internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudA
|
|||
.Where(x => x.GetAttribute<DalamudAssetAttribute>()?.Required is true)
|
||||
.Select(this.CreateStreamAsync)
|
||||
.Select(x => x.ToContentDisposedTask()))
|
||||
.ContinueWith(_ => loadTimings.Dispose()),
|
||||
.ContinueWith(
|
||||
r =>
|
||||
{
|
||||
loadTimings.Dispose();
|
||||
return r;
|
||||
})
|
||||
.Unwrap(),
|
||||
"Prevent Dalamud from loading more stuff, until we've ensured that all required assets are available.");
|
||||
|
||||
Task.WhenAll(
|
||||
|
|
@ -83,7 +89,7 @@ internal sealed class DalamudAssetManager : IServiceType, IDisposable, IDalamudA
|
|||
public IDalamudTextureWrap Empty4X4 => this.GetDalamudTextureWrap(DalamudAsset.Empty4X4);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,17 +22,22 @@ namespace Dalamud.Storage;
|
|||
/// This is not an early-loaded service, as it is needed before they are initialized.
|
||||
/// </remarks>
|
||||
[ServiceManager.ProvidedService]
|
||||
public class ReliableFileStorage : IServiceType, IDisposable
|
||||
[Api10ToDo("Make internal and IInternalDisposableService, and remove #pragma guard from the caller.")]
|
||||
public class ReliableFileStorage : IPublicDisposableService
|
||||
{
|
||||
private static readonly ModuleLog Log = new("VFS");
|
||||
|
||||
private readonly object syncRoot = new();
|
||||
|
||||
private SQLiteConnection? db;
|
||||
private bool isService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ReliableFileStorage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="vfsDbPath">Path to the VFS.</param>
|
||||
[Obsolete("Dalamud internal use only.", false)]
|
||||
[Api10ToDo("Make internal, and remove #pragma guard from the caller.")]
|
||||
public ReliableFileStorage(string vfsDbPath)
|
||||
{
|
||||
var databasePath = Path.Combine(vfsDbPath, "dalamudVfs.db");
|
||||
|
|
@ -60,7 +65,7 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check if a file exists.
|
||||
/// This will return true if the file does not exist on the filesystem, but in the transparent backup.
|
||||
|
|
@ -288,9 +293,20 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
|||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
this.db?.Dispose();
|
||||
if (!this.isService)
|
||||
this.DisposeCore();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
if (this.isService)
|
||||
this.DisposeCore();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
void IPublicDisposableService.MarkDisposeOnlyFromService() => this.isService = true;
|
||||
|
||||
/// <summary>
|
||||
/// Replace possible non-portable parts of a path with portable versions.
|
||||
/// </summary>
|
||||
|
|
@ -312,6 +328,8 @@ public class ReliableFileStorage : IServiceType, IDisposable
|
|||
this.db.CreateTable<DbFile>();
|
||||
}
|
||||
|
||||
private void DisposeCore() => this.db?.Dispose();
|
||||
|
||||
private class DbFile
|
||||
{
|
||||
[PrimaryKey]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue