From e98003eb09dac2d105d1597f8153ad27b7257ab3 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sat, 27 May 2023 15:43:37 +0200 Subject: [PATCH] Added some other task handling for collection caches. --- OtterGui | 2 +- Penumbra/Collections/Cache/CollectionCache.cs | 93 ++++++++++++++++--- .../Cache/CollectionCacheManager.cs | 27 +++--- Penumbra/Mods/Editor/ModBackup.cs | 5 +- Penumbra/Mods/Editor/ModNormalizer.cs | 2 +- Penumbra/Mods/Manager/ModExportManager.cs | 1 + Penumbra/Mods/Manager/ModManager.cs | 1 + Penumbra/Penumbra.cs | 8 +- Penumbra/Services/ConfigMigrationService.cs | 1 + Penumbra/Services/ServiceWrapper.cs | 5 +- Penumbra/UI/ModsTab/ModPanelEditTab.cs | 1 + 11 files changed, 110 insertions(+), 36 deletions(-) diff --git a/OtterGui b/OtterGui index d59cf504..73f6b14d 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit d59cf50483fc81af5deb871bac76f70d42d7b8c1 +Subproject commit 73f6b14d16920a94b7b98fe85973b9b2b959ada5 diff --git a/Penumbra/Collections/Cache/CollectionCache.cs b/Penumbra/Collections/Cache/CollectionCache.cs index 298e683c..1196a110 100644 --- a/Penumbra/Collections/Cache/CollectionCache.cs +++ b/Penumbra/Collections/Cache/CollectionCache.cs @@ -122,26 +122,40 @@ public class CollectionCache : IDisposable return ret; } + public void ForceFile(Utf8GamePath path, FullPath fullPath) + => _manager.AddChange(ChangeData.ForcedFile(this, path, fullPath)); + + public void RemovePath(Utf8GamePath path) + => _manager.AddChange(ChangeData.ForcedFile(this, path, FullPath.Empty)); + + public void ReloadMod(IMod mod, bool addMetaChanges) + => _manager.AddChange(ChangeData.ModReload(this, mod, addMetaChanges)); + + public void AddMod(IMod mod, bool addMetaChanges) + => _manager.AddChange(ChangeData.ModAddition(this, mod, addMetaChanges)); + + public void RemoveMod(IMod mod, bool addMetaChanges) + => _manager.AddChange(ChangeData.ModRemoval(this, mod, addMetaChanges)); + /// Force a file to be resolved to a specific path regardless of conflicts. - internal void ForceFile(Utf8GamePath path, FullPath fullPath) + private void ForceFileSync(Utf8GamePath path, FullPath fullPath) { if (!CheckFullPath(path, fullPath)) return; - - _manager.ForceFile(this, path, fullPath); + + if (ResolvedFiles.Remove(path, out var modPath)) + ModData.RemovePath(modPath.Mod, path); + if (fullPath.FullName.Length > 0) + ResolvedFiles.Add(path, new ModPath(Mod.ForcedFiles, fullPath)); } - /// Force a file resolve to be removed. - internal void RemovePath(Utf8GamePath path) - => _manager.ForceFile(this, path, FullPath.Empty); - - public void ReloadMod(IMod mod, bool addMetaChanges) + internal void ReloadModSync(IMod mod, bool addMetaChanges) { - RemoveMod(mod, addMetaChanges); - AddMod(mod, addMetaChanges); + RemoveModSync(mod, addMetaChanges); + AddModSync(mod, addMetaChanges); } - public void RemoveMod(IMod mod, bool addMetaChanges) + internal void RemoveModSync(IMod mod, bool addMetaChanges) { var conflicts = Conflicts(mod); var (paths, manipulations) = ModData.RemoveMod(mod); @@ -168,7 +182,7 @@ public class CollectionCache : IDisposable { if (conflict.HasPriority) { - ReloadMod(conflict.Mod2, false); + ReloadModSync(conflict.Mod2, false); } else { @@ -185,8 +199,8 @@ public class CollectionCache : IDisposable } - // Add all files and possibly manipulations of a given mod according to its settings in this collection. - public void AddMod(IMod mod, bool addMetaChanges) + /// Add all files and possibly manipulations of a given mod according to its settings in this collection. + internal void AddModSync(IMod mod, bool addMetaChanges) { if (mod.Index >= 0) { @@ -421,4 +435,55 @@ public class CollectionCache : IDisposable Penumbra.Log.Error($"The redirected path is too long to add the redirection\n\t{path}\n\t--> {fullPath}"); return false; } + + public readonly record struct ChangeData + { + public readonly CollectionCache Cache; + public readonly Utf8GamePath Path; + public readonly FullPath FullPath; + public readonly IMod Mod; + public readonly byte Type; + public readonly bool AddMetaChanges; + + private ChangeData(CollectionCache cache, Utf8GamePath p, FullPath fp, IMod m, byte t, bool a) + { + Cache = cache; + Path = p; + FullPath = fp; + Mod = m; + Type = t; + AddMetaChanges = a; + } + + public static ChangeData ModRemoval(CollectionCache cache, IMod mod, bool addMetaChanges) + => new(cache, Utf8GamePath.Empty, FullPath.Empty, mod, 0, addMetaChanges); + + public static ChangeData ModAddition(CollectionCache cache, IMod mod, bool addMetaChanges) + => new(cache, Utf8GamePath.Empty, FullPath.Empty, mod, 1, addMetaChanges); + + public static ChangeData ModReload(CollectionCache cache, IMod mod, bool addMetaChanges) + => new(cache, Utf8GamePath.Empty, FullPath.Empty, mod, 2, addMetaChanges); + + public static ChangeData ForcedFile(CollectionCache cache, Utf8GamePath p, FullPath fp) + => new(cache, p, fp, Mods.Mod.ForcedFiles, 3, false); + + public void Apply() + { + switch (Type) + { + case 0: + Cache.RemoveModSync(Mod, AddMetaChanges); + break; + case 1: + Cache.AddModSync(Mod, AddMetaChanges); + break; + case 2: + Cache.ReloadModSync(Mod, AddMetaChanges); + break; + case 3: + Cache.ForceFileSync(Path, FullPath); + break; + } + } + } } diff --git a/Penumbra/Collections/Cache/CollectionCacheManager.cs b/Penumbra/Collections/Cache/CollectionCacheManager.cs index a14c6ac2..0c084c5c 100644 --- a/Penumbra/Collections/Cache/CollectionCacheManager.cs +++ b/Penumbra/Collections/Cache/CollectionCacheManager.cs @@ -15,7 +15,6 @@ using Penumbra.Meta; using Penumbra.Mods; using Penumbra.Mods.Manager; using Penumbra.Services; -using Penumbra.String.Classes; namespace Penumbra.Collections.Cache; @@ -30,7 +29,7 @@ public class CollectionCacheManager : IDisposable internal readonly MetaFileManager MetaFileManager; - private readonly ConcurrentQueue<(CollectionCache, Utf8GamePath, FullPath)> _forcedFileQueue = new(); + private readonly ConcurrentQueue _changeQueue = new(); private int _count; @@ -81,6 +80,14 @@ public class CollectionCacheManager : IDisposable MetaFileManager.CharacterUtility.LoadingFinished -= IncrementCounters; } + public void AddChange(CollectionCache.ChangeData data) + { + if (_framework.Framework.IsInFrameworkUpdateThread) + data.Apply(); + else + _changeQueue.Enqueue(data); + } + /// Only creates a new cache, does not update an existing one. public bool CreateCache(ModCollection collection) { @@ -102,9 +109,6 @@ public class CollectionCacheManager : IDisposable => _framework.RegisterImportant(nameof(CalculateEffectiveFileList) + collection.Name, () => CalculateEffectiveFileListInternal(collection)); - public void ForceFile(CollectionCache cache, Utf8GamePath path, FullPath fullPath) - => _forcedFileQueue.Enqueue((cache, path, fullPath)); - private void CalculateEffectiveFileListInternal(ModCollection collection) { // Skip the empty collection. @@ -143,10 +147,10 @@ public class CollectionCacheManager : IDisposable .Concat(_tempMods.Mods.TryGetValue(collection, out var list) ? list : Array.Empty())) - cache.AddMod(tempMod, false); + cache.AddModSync(tempMod, false); foreach (var mod in _modStorage) - cache.AddMod(mod, false); + cache.AddModSync(mod, false); cache.AddMetaFiles(); @@ -351,12 +355,7 @@ public class CollectionCacheManager : IDisposable /// private void OnFramework(Framework _) { - while (_forcedFileQueue.TryDequeue(out var tuple)) - { - if (tuple.Item1.ResolvedFiles.Remove(tuple.Item2, out var modPath)) - tuple.Item1.ModData.RemovePath(modPath.Mod, tuple.Item2); - if (tuple.Item3.FullName.Length > 0) - tuple.Item1.ResolvedFiles.Add(tuple.Item2, new ModPath(Mod.ForcedFiles, tuple.Item3)); - } + while (_changeQueue.TryDequeue(out var changeData)) + changeData.Apply(); } } diff --git a/Penumbra/Mods/Editor/ModBackup.cs b/Penumbra/Mods/Editor/ModBackup.cs index 72680091..cbb98a38 100644 --- a/Penumbra/Mods/Editor/ModBackup.cs +++ b/Penumbra/Mods/Editor/ModBackup.cs @@ -3,9 +3,10 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Threading.Tasks; +using OtterGui; using Penumbra.Mods.Manager; -namespace Penumbra.Mods; +namespace Penumbra.Mods.Editor; /// Utility to create and apply a zipped backup of a mod. public class ModBackup @@ -80,7 +81,7 @@ public class ModBackup return; CreatingBackup = true; - await Task.Run(Create); + await AsyncTask.Run(Create); CreatingBackup = false; } diff --git a/Penumbra/Mods/Editor/ModNormalizer.cs b/Penumbra/Mods/Editor/ModNormalizer.cs index 8a918ec6..0019b5f6 100644 --- a/Penumbra/Mods/Editor/ModNormalizer.cs +++ b/Penumbra/Mods/Editor/ModNormalizer.cs @@ -41,7 +41,7 @@ public class ModNormalizer Step = 0; TotalSteps = mod.TotalFileCount + 5; - Worker = Task.Run(NormalizeSync); + Worker = TrackedTask.Run(NormalizeSync); } private void NormalizeSync() diff --git a/Penumbra/Mods/Manager/ModExportManager.cs b/Penumbra/Mods/Manager/ModExportManager.cs index 6bb919fc..f2bfb9bc 100644 --- a/Penumbra/Mods/Manager/ModExportManager.cs +++ b/Penumbra/Mods/Manager/ModExportManager.cs @@ -1,6 +1,7 @@ using System; using System.IO; using Penumbra.Communication; +using Penumbra.Mods.Editor; using Penumbra.Services; namespace Penumbra.Mods.Manager; diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs index 7e7599f0..6c1ff9ab 100644 --- a/Penumbra/Mods/Manager/ModManager.cs +++ b/Penumbra/Mods/Manager/ModManager.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using Penumbra.Communication; +using Penumbra.Mods.Editor; using Penumbra.Services; namespace Penumbra.Mods.Manager; diff --git a/Penumbra/Penumbra.cs b/Penumbra/Penumbra.cs index 4876d530..bd530ccd 100644 --- a/Penumbra/Penumbra.cs +++ b/Penumbra/Penumbra.cs @@ -52,10 +52,14 @@ public class Penumbra : IDalamudPlugin try { var startTimer = new StartTracker(); - using var timer = startTimer.Measure(StartTimeType.Total); + using var timer = startTimer.Measure(StartTimeType.Total); _services = ServiceManager.CreateProvider(this, pluginInterface, Log, startTimer); ChatService = _services.GetRequiredService(); _validityChecker = _services.GetRequiredService(); + var startup = _services.GetRequiredService().GetDalamudConfig(DalamudServices.WaitingForPluginsOption, out bool s) + ? s.ToString() + : "Unknown"; + Log.Information($"Loading Penumbra Version {_validityChecker.Version}, Commit #{_validityChecker.CommitHash} with Waiting For Plugins: {startup}..."); _services.GetRequiredService(); // Initialize because not required anywhere else. _config = _services.GetRequiredService(); _characterUtility = _services.GetRequiredService(); @@ -114,7 +118,7 @@ public class Penumbra : IDalamudPlugin private void SetupInterface() { - Task.Run(() => + AsyncTask.Run(() => { using var tInterface = _services.GetRequiredService().Measure(StartTimeType.Interface); var system = _services.GetRequiredService(); diff --git a/Penumbra/Services/ConfigMigrationService.cs b/Penumbra/Services/ConfigMigrationService.cs index 8c0a60f1..5d19dbe5 100644 --- a/Penumbra/Services/ConfigMigrationService.cs +++ b/Penumbra/Services/ConfigMigrationService.cs @@ -9,6 +9,7 @@ using Penumbra.Collections; using Penumbra.Collections.Manager; using Penumbra.Interop.Services; using Penumbra.Mods; +using Penumbra.Mods.Editor; using Penumbra.Mods.Manager; using Penumbra.UI.Classes; using Penumbra.Util; diff --git a/Penumbra/Services/ServiceWrapper.cs b/Penumbra/Services/ServiceWrapper.cs index cb4c86e8..5a43cf9a 100644 --- a/Penumbra/Services/ServiceWrapper.cs +++ b/Penumbra/Services/ServiceWrapper.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using OtterGui; using Penumbra.Util; namespace Penumbra.Services; @@ -58,7 +59,7 @@ public abstract class AsyncServiceWrapper protected AsyncServiceWrapper(string name, StartTracker tracker, StartTimeType type, Func factory) { Name = name; - _task = Task.Run(() => + _task = TrackedTask.Run(() => { using var timer = tracker.Measure(type); var service = factory(); @@ -84,7 +85,7 @@ public abstract class AsyncServiceWrapper protected AsyncServiceWrapper(string name, Func factory) { Name = name; - _task = Task.Run(() => + _task = TrackedTask.Run(() => { var service = factory(); if (_isDisposed) diff --git a/Penumbra/UI/ModsTab/ModPanelEditTab.cs b/Penumbra/UI/ModsTab/ModPanelEditTab.cs index 294f8041..f5b03659 100644 --- a/Penumbra/UI/ModsTab/ModPanelEditTab.cs +++ b/Penumbra/UI/ModsTab/ModPanelEditTab.cs @@ -12,6 +12,7 @@ using OtterGui.Raii; using OtterGui.Widgets; using Penumbra.Api.Enums; using Penumbra.Mods; +using Penumbra.Mods.Editor; using Penumbra.Mods.Manager; using Penumbra.Services; using Penumbra.UI.AdvancedWindow;