namespace Phantom.Utils.Runtime; 

public sealed class CancellableSemaphore : IDisposable {
	private readonly SemaphoreSlim semaphore;
	private readonly CancellationTokenSource cancellationTokenSource = new ();
	
	public CancellableSemaphore(int initialCount, int maxCount) {
		this.semaphore = new SemaphoreSlim(initialCount, maxCount);
	}

	public async Task<bool> Wait(TimeSpan timeout, CancellationToken cancellationToken) {
		return await semaphore.WaitAsync(timeout, cancellationTokenSource.Token).WaitAsync(cancellationToken);
	}

	public async Task<bool> CancelAndWait(TimeSpan timeout) {
		cancellationTokenSource.Cancel();
		return await semaphore.WaitAsync(timeout);
	}

	public void Release() {
		semaphore.Release();
	}
	
	public void Dispose() {
		semaphore.Dispose();
		cancellationTokenSource.Dispose();
	}
}