1
0
mirror of https://github.com/chylex/.NET-Community-Toolkit.git synced 2025-08-16 05:31:46 +02:00
Files
.github
CommunityToolkit.Common
CommunityToolkit.Diagnostics
CommunityToolkit.HighPerformance
Attributes
Buffers
Enumerables
Extensions
ArrayExtensions.1D.cs
ArrayExtensions.2D.cs
ArrayExtensions.3D.cs
ArrayPoolBufferWriterExtensions.cs
ArrayPoolExtensions.cs
BoolExtensions.cs
HashCodeExtensions.cs
IBufferWriterExtensions.cs
IMemoryOwnerExtensions.cs
ListExtensions.cs
MemoryExtensions.cs
NullableExtensions.cs
ReadOnlyMemoryExtensions.cs
ReadOnlySpanExtensions.cs
SpanExtensions.cs
SpinLockExtensions.cs
StreamExtensions.cs
StringExtensions.cs
Helpers
Memory
Properties
Streams
Box{T}.cs
CommunityToolkit.HighPerformance.csproj
NullableReadOnlyRef{T}.cs
NullableRef{T}.cs
ReadOnlyRef{T}.cs
Ref{T}.cs
CommunityToolkit.Mvvm
CommunityToolkit.Mvvm.SourceGenerators
build
tests
.editorconfig
.git-blame-ignore-revs
.gitattributes
.gitignore
.runsettings
CODE_OF_CONDUCT.md
Contributing.md
Directory.Build.props
Directory.Build.targets
License.md
README.md
ThirdPartyNotices.txt
azure-pipelines.yml
dotnet Community Toolkit.sln
toolkit.snk
version.json
Sergio Pedri 40d06fa8e5 Fix XML docs
2022-03-28 14:04:49 +02:00

155 lines
6.3 KiB
C#

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.ComponentModel;
using System.Runtime.CompilerServices;
#if NETSTANDARD2_1_OR_GREATER
using System.Runtime.Versioning;
#endif
using System.Threading;
namespace CommunityToolkit.HighPerformance;
/// <summary>
/// Helpers for working with the <see cref="SpinLock"/> type.
/// </summary>
public static class SpinLockExtensions
{
/// <summary>
/// Enters a specified <see cref="SpinLock"/> instance and returns a wrapper to use to release the lock.
/// This extension should be used though a <see langword="using"/> block or statement:
/// <code>
/// SpinLock spinLock = new SpinLock();
///
/// using (SpinLockExtensions.Enter(&amp;spinLock))
/// {
/// // Thread-safe code here...
/// }
/// </code>
/// The compiler will take care of releasing the SpinLock when the code goes out of that <see langword="using"/> scope.
/// </summary>
/// <param name="spinLock">A pointer to the target <see cref="SpinLock"/> to use</param>
/// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns>
/// <remarks>The returned <see cref="UnsafeLock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe UnsafeLock Enter(SpinLock* spinLock)
{
return new(spinLock);
}
/// <summary>
/// A <see langword="struct"/> that is used to enter and hold a <see cref="SpinLock"/> through a <see langword="using"/> block or statement.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly unsafe ref struct UnsafeLock
{
/// <summary>
/// The <see cref="SpinLock"/>* pointer to the target <see cref="SpinLock"/> value to use.
/// </summary>
private readonly SpinLock* spinLock;
/// <summary>
/// A value indicating whether or not the lock is taken by this <see cref="UnsafeLock"/> instance.
/// </summary>
private readonly bool lockTaken;
/// <summary>
/// Initializes a new instance of the <see cref="UnsafeLock"/> struct.
/// </summary>
/// <param name="spinLock">The target <see cref="SpinLock"/> to use.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal UnsafeLock(SpinLock* spinLock)
{
this.spinLock = spinLock;
this.lockTaken = false;
spinLock->Enter(ref this.lockTaken);
}
/// <summary>
/// Implements the duck-typed <see cref="System.IDisposable.Dispose"/> method and releases the current <see cref="SpinLock"/> instance.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
if (this.lockTaken)
{
this.spinLock->Exit();
}
}
}
#if NETSTANDARD2_1_OR_GREATER
/// <summary>
/// Enters a specified <see cref="SpinLock"/> instance and returns a wrapper to use to release the lock.
/// This extension should be used though a <see langword="using"/> block or statement:
/// <code>
/// SpinLock spinLock = new SpinLock();
///
/// using (spinLock.Enter())
/// {
/// // Thread-safe code here...
/// }
/// </code>
/// The compiler will take care of releasing the SpinLock when the code goes out of that <see langword="using"/> scope.
/// </summary>
/// <param name="spinLock">The target <see cref="SpinLock"/> to use</param>
/// <returns>A wrapper type that will release <paramref name="spinLock"/> when its <see cref="System.IDisposable.Dispose"/> method is called.</returns>
/// <remarks>The returned <see cref="Lock"/> value shouldn't be used directly: use this extension in a <see langword="using"/> block or statement.</remarks>
[RequiresPreviewFeatures(
"The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
Url = "https://github.com/dotnet/runtime/issues/46104")]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Lock Enter(ref this SpinLock spinLock)
{
return new(ref spinLock);
}
/// <summary>
/// A <see langword="struct"/> that is used to enter and hold a <see cref="SpinLock"/> through a <see langword="using"/> block or statement.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[RequiresPreviewFeatures(
"The Lock type has no compiler support to ensure the lifetime of referenced values is respected, and as such using it incorrectly may lead to GC holes.",
Url = "https://github.com/dotnet/runtime/issues/46104")]
public readonly ref struct Lock
{
/// <summary>
/// The <see cref="Ref{T}"/> instance pointing to the target <see cref="SpinLock"/> value to use.
/// </summary>
private readonly Ref<SpinLock> spinLock;
/// <summary>
/// A value indicating whether or not the lock is taken by this <see cref="Lock"/> instance.
/// </summary>
private readonly bool lockTaken;
/// <summary>
/// Initializes a new instance of the <see cref="Lock"/> struct.
/// </summary>
/// <param name="spinLock">The target <see cref="SpinLock"/> to use.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Lock(ref SpinLock spinLock)
{
this.spinLock = new Ref<SpinLock>(ref spinLock);
this.lockTaken = false;
spinLock.Enter(ref this.lockTaken);
}
/// <summary>
/// Implements the duck-typed <see cref="System.IDisposable.Dispose"/> method and releases the current <see cref="SpinLock"/> instance.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Dispose()
{
if (this.lockTaken)
{
this.spinLock.Value.Exit();
}
}
}
#endif
}