Files
Nicolas Musset 41381dedd5 refactor: Nullable and Modernization for Core projects (#2643)
* [Core.Mathematics] Modernize code

* [Core.Mathematics] Add tests to Stride.Tests.Simple

* [Core] Cleanup some code

* [Core.CompilerServices] Cleanup some code

* [Core.CompilerServices] Add tests to Stride.Tests.Simple

* [Core.IO] Modernize code

* [Core.MicroThreading] Modernize code

* [Core.Serialization] Modernize code

* [Core.AssemblyProcessor.Tests] Modernize code

* [Core.CompilerServices.Tests] Modernize code

* [Core.Mathematics.Tests] Modernize code

* [Core.Tests] Modernize code

* [Core.Translation] Modernize code

* [Core.Reflection] Modernize code

* Fixes build of Stride.VisualStudio.sln

* [Core.Yaml.Tests] Modernize code

* [Core.Design] Modernize code

* [Core.Design.Tests] Modernize code

* [Core.Mathematics] More annotations

* Fix build of projects that import code from Core.Design

Especially those targeting .NET Framework
2025-02-22 16:50:47 +01:00

127 lines
3.6 KiB
C#

// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Runtime.CompilerServices;
namespace Stride.Core.MicroThreading;
/// <summary>
/// Provides microthread-local storage of data.
/// </summary>
/// <typeparam name="T">Type of data stored.</typeparam>
public class MicroThreadLocal<T> where T : class
{
private readonly Func<T>? valueFactory;
private readonly ConditionalWeakTable<MicroThread, T?> values = [];
/// <summary>
/// The value return when we are not in a micro thread. That is the value return when 'Scheduler.CurrentMicroThread==null'
/// </summary>
private T? valueOutOfMicrothread;
/// <summary>
/// Indicate if the value out of micro-thread have been set at least once or not.
/// </summary>
private bool valueOutOfMicrothreadSet;
/// <summary>
/// Initializes a new instance of the <see cref="MicroThreadLocal{T}"/> class.
/// </summary>
public MicroThreadLocal()
: this(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="MicroThreadLocal{T}"/> class.
/// </summary>
/// <param name="valueFactory">The value factory invoked to create a value when <see cref="Value"/> is retrieved before having been previously initialized.</param>
public MicroThreadLocal(Func<T>? valueFactory)
{
this.valueFactory = valueFactory;
}
/// <summary>
/// Gets or sets the value for the current microthread.
/// </summary>
/// <value>
/// The value for the current microthread.
/// </value>
public T? Value
{
get
{
T? value;
var microThread = Scheduler.CurrentMicroThread;
lock (values)
{
if (microThread == null)
{
if (!valueOutOfMicrothreadSet)
valueOutOfMicrothread = valueFactory?.Invoke();
value = valueOutOfMicrothread;
}
else if (!values.TryGetValue(microThread, out value))
{
values.Add(microThread, value = valueFactory?.Invoke());
}
}
return value;
}
set
{
var microThread = Scheduler.CurrentMicroThread;
lock (values)
{
if (microThread == null)
{
valueOutOfMicrothread = value;
valueOutOfMicrothreadSet = true;
}
else
{
values.Remove(microThread);
values.Add(microThread, value);
}
}
}
}
public bool IsValueCreated
{
get
{
var microThread = Scheduler.CurrentMicroThread;
lock (values)
{
if (microThread == null)
return valueOutOfMicrothreadSet;
return values.TryGetValue(microThread, out var value);
}
}
}
public void ClearValue()
{
var microThread = Scheduler.CurrentMicroThread;
lock (values)
{
if (microThread == null)
{
valueOutOfMicrothread = default;
valueOutOfMicrothreadSet = false;
}
else
{
values.Remove(microThread);
}
}
}
}