Skip to content

Commit

Permalink
Use a workaround class To replace AsyncLocal
Browse files Browse the repository at this point in the history
  • Loading branch information
maxisoft committed Dec 3, 2024
1 parent c42f356 commit 59bc2bf
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
2 changes: 1 addition & 1 deletion ASFFreeGames/ASFFreeGamesPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ internal static PluginContext Context {
}

// ReSharper disable once InconsistentNaming
private static readonly ThreadLocal<PluginContext> _context = new();
private static readonly Utils.Workarounds.AsyncLocal<PluginContext> _context = new();
private static CancellationToken CancellationToken => Context.CancellationToken;

public string Name => StaticName;
Expand Down
75 changes: 75 additions & 0 deletions ASFFreeGames/Utils/Workarounds/AsyncLocal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System;

namespace Maxisoft.ASF.Utils.Workarounds;

public sealed class AsyncLocal<T> {
// ReSharper disable once StaticMemberInGenericType
private static readonly Type? AsyncLocalType;

#pragma warning disable CA1810
static AsyncLocal() {
#pragma warning restore CA1810
try {
AsyncLocalType = Type.GetType("System.Threading.AsyncLocal`1")
?.MakeGenericType(typeof(T));
}
catch (InvalidOperationException) {
// ignore
}

try {
AsyncLocalType ??= Type.GetType("System.Threading.AsyncLocal")
?.MakeGenericType(typeof(T));
}

catch (InvalidOperationException) {
// ignore
}
}

private readonly dynamic? Delegate;
private T? NonSafeValue;

/// <summary>Instantiates an <see cref="AsyncLocal{T}"/> instance that does not receive change notifications.</summary>
public AsyncLocal() {
if (AsyncLocalType is not null) {
try {
Delegate = Activator.CreateInstance(AsyncLocalType)!;
}
catch (SystemException) {
// ignored
}
}
}

/// <summary>Gets or sets the value of the ambient data.</summary>
/// <value>The value of the ambient data. If no value has been set, the returned value is default(T).</value>
public T? Value {
get {
if (Delegate is not null) {
try {
return Delegate.Value;
}
catch (SystemException) {
// ignored
}
}

return (T) NonSafeValue!;
}
set {
if (Delegate is not null) {
try {
Delegate.Value = value!;

return;
}
catch (SystemException) {
// ignored
}
}

NonSafeValue = value;
}
}
}

0 comments on commit 59bc2bf

Please sign in to comment.