aspnetcore/src/Microsoft.AspNetCore.Server.../Overlapped/DeferredDisposableLifetime.cs

88 lines
2.5 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#if !NETSTANDARD1_3 // TODO: Temp copy. Remove once we target net46.
using System;
namespace System.Threading
{
internal struct DeferredDisposableLifetime<T> where T : class, IDeferredDisposable
{
private int _count;
public bool AddRef(T obj)
{
while (true)
{
int num = Volatile.Read(ref this._count);
if (num < 0)
{
break;
}
int num2 = checked(num + 1);
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
return true;
}
}
throw new ObjectDisposedException(typeof(T).ToString());
}
public void Release(T obj)
{
int num2;
int num3;
while (true)
{
int num = Volatile.Read(ref this._count);
if (num > 0)
{
num2 = num - 1;
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
break;
}
}
else
{
num3 = num + 1;
if (Interlocked.CompareExchange(ref this._count, num3, num) == num)
{
goto Block_3;
}
}
}
if (num2 == 0)
{
obj.OnFinalRelease(false);
}
return;
Block_3:
if (num3 == -1)
{
obj.OnFinalRelease(true);
}
}
public void Dispose(T obj)
{
int num2;
while (true)
{
int num = Volatile.Read(ref this._count);
if (num < 0)
{
break;
}
num2 = -1 - num;
if (Interlocked.CompareExchange(ref this._count, num2, num) == num)
{
goto Block_1;
}
}
return;
Block_1:
if (num2 == -1)
{
obj.OnFinalRelease(true);
}
}
}
}
#endif