|
// 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.
namespace Xunit.Threading
{
using System;
using System.Threading;
using System.Threading.Tasks;
internal static class SemaphoreExtensions
{
public static SemaphoreDisposer DisposableWait(this Semaphore semaphore, CancellationToken cancellationToken)
{
if (cancellationToken.CanBeCanceled)
{
var signalledIndex = WaitHandle.WaitAny(new[] { semaphore, cancellationToken.WaitHandle });
if (signalledIndex != 0)
{
cancellationToken.ThrowIfCancellationRequested();
throw ExceptionUtilities.Unreachable;
}
}
else
{
semaphore.WaitOne();
}
return new SemaphoreDisposer(semaphore);
}
public static Task<SemaphoreDisposer> DisposableWaitAsync(this Semaphore semaphore, CancellationToken cancellationToken)
{
return Task.Factory.StartNew(
() => DisposableWait(semaphore, cancellationToken),
cancellationToken,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
internal struct SemaphoreDisposer : IDisposable
{
private readonly Semaphore _semaphore;
public SemaphoreDisposer(Semaphore semaphore)
{
_semaphore = semaphore;
}
public void Dispose()
{
_semaphore.Release();
}
}
}
}
|