/// <summary> /// ロックを行います。即座にロックできない場合、ロックに成功するまで待機します。 /// </summary> /// <returns>ロック コンテキスト。<see cref="IDisposable.Dispose" />の呼び出しでロックを開放します。</returns> public async Task <Context> EnterAsync() { if (Interlocked.Exchange(ref locked, 1) == 1) { var ev = new Awaiter <T>(); queue.Enqueue(ev); await ev.WaitAsync(); } return(new Context(this)); }
bool TryDequeue(out Awaiter <T> ev) { while (true) { var result = queue.TryDequeue(out ev); if (result && ev.IsCompleted) { continue; } return(result); } }
/// <summary> /// ロックを行います。即座にロックできない場合、ロックに成功するか、タイムアウトするか、キャンセルされるまで処理をブロックします。 /// </summary> /// <returns>ロック コンテキスト。<see cref="IDisposable.Dispose" />の呼び出しでロックを開放します。</returns> public Context Enter(TimeSpan timeout, CancellationToken cancellationToken) { if (Interlocked.Exchange(ref locked, 1) == 1) { using var ev = new Awaiter <T>(); queue.Enqueue(ev); if (!ev.Wait(timeout, cancellationToken)) { return(Context.Failed); } } return(new Context(this)); }
public Awaitable(Awaiter <T> awaiter) => this.awaiter = awaiter;