mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-02-14 20:07:43 +01:00
* Use new Lock objects * Fix CA1513: Use ObjectDisposedException.ThrowIf * Fix CA1860: Avoid using 'Enumerable.Any()' extension method * Fix IDE0028: Use collection initializers or expressions * Fix CA2263: Prefer generic overload when type is known * Fix CA1862: Use the 'StringComparison' method overloads to perform case-insensitive string comparisons * Fix IDE0270: Null check can be simplified * Fix IDE0280: Use 'nameof' * Fix IDE0009: Add '.this' * Fix IDE0007: Use 'var' instead of explicit type * Fix IDE0062: Make local function static * Fix CA1859: Use concrete types when possible for improved performance * Fix IDE0066: Use switch expression Only applied to where it doesn't look horrendous. * Use is over switch * Fix CA1847: Use String.Contains(char) instead of String.Contains(string) with single characters * Fix SYSLIB1045: Use 'GeneratedRegexAttribute' to generate the regular expression implementation at compile-time. * Fix CA1866: Use 'string.EndsWith(char)' instead of 'string.EndsWith(string)' when you have a string with a single char * Fix IDE0057: Substring can be simplified * Fix IDE0059: Remove unnecessary value assignment * Fix CA1510: Use ArgumentNullException throw helper * Fix IDE0300: Use collection expression for array * Fix IDE0250: Struct can be made 'readonly' * Fix IDE0018: Inline variable declaration * Fix CA1850: Prefer static HashData method over ComputeHash * Fi CA1872: Prefer 'Convert.ToHexString' and 'Convert.ToHexStringLower' over call chains based on 'BitConverter.ToString' * Update ModuleLog instantiations * Organize usings
114 lines
4.2 KiB
C#
114 lines
4.2 KiB
C#
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.ExceptionServices;
|
|
|
|
using Dalamud.Plugin.Ipc.Exceptions;
|
|
|
|
using Serilog;
|
|
|
|
namespace Dalamud.Plugin.Ipc.Internal;
|
|
|
|
/// <summary>
|
|
/// A helper struct for reference-counted, type-safe shared access across plugin boundaries.
|
|
/// </summary>
|
|
internal readonly struct DataCache
|
|
{
|
|
/// <summary> Name of the data. </summary>
|
|
internal readonly string Tag;
|
|
|
|
/// <summary> The assembly name of the initial creator. </summary>
|
|
internal readonly string CreatorAssemblyName;
|
|
|
|
/// <summary> A not-necessarily distinct list of current users. </summary>
|
|
/// <remarks> Also used as a reference count tracker. </remarks>
|
|
internal readonly List<string> UserAssemblyNames;
|
|
|
|
/// <summary> The type the data was registered as. </summary>
|
|
internal readonly Type Type;
|
|
|
|
/// <summary> A reference to data. </summary>
|
|
internal readonly object? Data;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="DataCache"/> struct.
|
|
/// </summary>
|
|
/// <param name="tag">Name of the data.</param>
|
|
/// <param name="creatorAssemblyName">The assembly name of the initial creator.</param>
|
|
/// <param name="data">A reference to data.</param>
|
|
/// <param name="type">The type of the data.</param>
|
|
public DataCache(string tag, string creatorAssemblyName, object? data, Type type)
|
|
{
|
|
this.Tag = tag;
|
|
this.CreatorAssemblyName = creatorAssemblyName;
|
|
this.UserAssemblyNames = [];
|
|
this.Data = data;
|
|
this.Type = type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new instance of the <see cref="DataCache"/> struct, using the given data generator function.
|
|
/// </summary>
|
|
/// <param name="tag">The name for the data cache.</param>
|
|
/// <param name="creatorAssemblyName">The assembly name of the initial creator.</param>
|
|
/// <param name="dataGenerator">The function that generates the data if it does not already exist.</param>
|
|
/// <typeparam name="T">The type of the stored data - needs to be a reference type that is shared through Dalamud itself, not loaded by the plugin.</typeparam>
|
|
/// <returns>The new instance of <see cref="DataCache"/>.</returns>
|
|
public static DataCache From<T>(string tag, string creatorAssemblyName, Func<T> dataGenerator)
|
|
where T : class
|
|
{
|
|
try
|
|
{
|
|
var result = new DataCache(tag, creatorAssemblyName, dataGenerator.Invoke(), typeof(T));
|
|
Log.Verbose(
|
|
"[{who}] Created new data for [{Tag:l}] for creator {Creator:l}.",
|
|
nameof(DataShare),
|
|
tag,
|
|
creatorAssemblyName);
|
|
return result;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw ExceptionDispatchInfo.SetCurrentStackTrace(
|
|
new DataCacheCreationError(tag, creatorAssemblyName, typeof(T), e));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Attempts to fetch the data.
|
|
/// </summary>
|
|
/// <param name="callerName">The name of the caller assembly.</param>
|
|
/// <param name="value">The value, if succeeded.</param>
|
|
/// <param name="ex">The exception, if failed.</param>
|
|
/// <typeparam name="T">Desired type of the data.</typeparam>
|
|
/// <returns><c>true</c> on success.</returns>
|
|
public bool TryGetData<T>(
|
|
string callerName,
|
|
[NotNullWhen(true)] out T? value,
|
|
[NotNullWhen(false)] out Exception? ex)
|
|
where T : class
|
|
{
|
|
switch (this.Data)
|
|
{
|
|
case null:
|
|
value = null;
|
|
ex = ExceptionDispatchInfo.SetCurrentStackTrace(new DataCacheValueNullError(this.Tag, this.Type));
|
|
return false;
|
|
|
|
case T data:
|
|
value = data;
|
|
ex = null;
|
|
|
|
// Register the access history
|
|
lock (this.UserAssemblyNames)
|
|
this.UserAssemblyNames.Add(callerName);
|
|
|
|
return true;
|
|
|
|
default:
|
|
value = null;
|
|
ex = ExceptionDispatchInfo.SetCurrentStackTrace(
|
|
new DataCacheTypeMismatchError(this.Tag, this.CreatorAssemblyName, typeof(T), this.Type));
|
|
return false;
|
|
}
|
|
}
|
|
}
|