From 293590bd5132e359de836a247d124b0b521bdcad Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Fri, 28 Oct 2022 16:54:17 +0200 Subject: [PATCH] Slight style updates, make caches to structs. --- Dalamud/Plugin/DalamudPluginInterface.cs | 16 +++++------ Dalamud/Plugin/Ipc/Internal/DataCache.cs | 34 +++++++++++++++++------- Dalamud/Plugin/Ipc/Internal/DataShare.cs | 28 ++++++++++++++++--- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs index 95b2e3e80..055b34cb1 100644 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ b/Dalamud/Plugin/DalamudPluginInterface.cs @@ -175,21 +175,21 @@ namespace Dalamud.Plugin #region IPC - /// + /// public T GetOrCreateData(string tag, Func dataGenerator) where T : class - => Service.Get().GetOrCreateData(tag, dataGenerator); + => Service.Get().GetOrCreateData(tag, dataGenerator); - /// + /// public void RelinquishData(string tag) - => Service.Get().RelinquishData(tag); + => Service.Get().RelinquishData(tag); - /// + /// public bool TryGetData(string tag, [NotNullWhen(true)] out T? data) where T : class - => Service.Get().TryGetData(tag, out data); + => Service.Get().TryGetData(tag, out data); - /// + /// public T? GetData(string tag) where T : class - => Service.Get().GetData(tag); + => Service.Get().GetData(tag); /// /// Gets an IPC provider. diff --git a/Dalamud/Plugin/Ipc/Internal/DataCache.cs b/Dalamud/Plugin/Ipc/Internal/DataCache.cs index d404cbba2..c357f77c2 100644 --- a/Dalamud/Plugin/Ipc/Internal/DataCache.cs +++ b/Dalamud/Plugin/Ipc/Internal/DataCache.cs @@ -3,18 +3,34 @@ using System.Collections.Generic; namespace Dalamud.Plugin.Ipc.Internal; -internal class DataCache +/// +/// A helper struct for reference-counted, type-safe shared access across plugin boundaries. +/// +internal readonly struct DataCache { - internal readonly string CreatorAssemblyName; - internal readonly List UserAssemblyNames; - internal readonly Type Type; - internal readonly object? Data; + /// The assembly name of the initial creator. + internal readonly string CreatorAssemblyName; - internal DataCache(string creatorAssemblyName, object? data, Type type) + /// A not-necessarily distinct list of current users. + internal readonly List UserAssemblyNames; + + /// The type the data was registered as. + internal readonly Type Type; + + /// A reference to data. + internal readonly object? Data; + + /// + /// Initializes a new instance of the struct. + /// + /// The assembly name of the initial creator. + /// A reference to data. + /// The type of the data. + public DataCache(string creatorAssemblyName, object? data, Type type) { this.CreatorAssemblyName = creatorAssemblyName; - this.UserAssemblyNames = new List{ creatorAssemblyName }; - this.Data = data; - this.Type = type; + this.UserAssemblyNames = new List { creatorAssemblyName }; + this.Data = data; + this.Type = type; } } diff --git a/Dalamud/Plugin/Ipc/Internal/DataShare.cs b/Dalamud/Plugin/Ipc/Internal/DataShare.cs index f22d9848c..d0c080e28 100644 --- a/Dalamud/Plugin/Ipc/Internal/DataShare.cs +++ b/Dalamud/Plugin/Ipc/Internal/DataShare.cs @@ -2,10 +2,14 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Reflection; + using Dalamud.Plugin.Ipc.Exceptions; namespace Dalamud.Plugin.Ipc.Internal; +/// +/// This class facilitates sharing data-references of standard types between plugins without using more expensive IPC. +/// [ServiceManager.EarlyLoadedService] internal class DataShare : IServiceType { @@ -45,7 +49,7 @@ internal class DataShare : IServiceType if (obj == null) throw new Exception("Returned data was null."); - cache = new DataCache(callerName, obj, typeof(T)); + cache = new DataCache(callerName, obj, typeof(T)); this.caches[tag] = cache; return obj; } @@ -104,7 +108,23 @@ internal class DataShare : IServiceType /// /// The type for the requested data - needs to be a reference type. /// The name for the data cache. - /// The requested data on success or null. - public T? GetData(string tag) where T : class - => TryGetData(tag, out var data) ? data : null; + /// The requested data + /// Thrown if is not registered. + /// Thrown if a cache for exists, but contains data of a type not assignable to . + /// Thrown if the stored data for a cache is null. + public T GetData(string tag) where T : class + { + if (!this.caches.TryGetValue(tag, out var cache)) + throw new KeyNotFoundException($"The data cache {tag} is not registered."); + + var callerName = Assembly.GetCallingAssembly().GetName().Name ?? string.Empty; + if (!cache.Type.IsAssignableTo(typeof(T))) + throw new DataCacheTypeMismatchError(tag, callerName, typeof(T), cache.Type); + + if (cache.Data is not T data) + throw new DataCacheValueNullError(tag, typeof(T)); + + cache.UserAssemblyNames.Add(callerName); + return data; + } }