/// <summary> /// Removes and returns an item from one of the specified collections in an asynchronous manner. /// </summary> public static ValueTask <AnyResult <T> > TakeFromAnyAsync(AsyncCollection <T>[] collections, CancellationToken cancellationToken) { if (collections == null) { throw new ArgumentNullException("collections"); } if (collections.Length <= 0 || collections.Length > TakeFromAnyMaxCollections) { throw new ArgumentException(String.Format("The collection array can't contain less than 1 or more than {0} collections.", TakeFromAnyMaxCollections), "collections"); } if (cancellationToken.IsCancellationRequested) { return(CanceledValueTask <AnyResult <T> > .Value); } ExclusiveCompletionSourceGroup <T> exclusiveSources = new ExclusiveCompletionSourceGroup <T>(); // Fast route: we attempt to take from the top-priority queues that have any items. // If the fast route succeeds, we avoid allocating and queueing a bunch of awaiters. for (int i = 0; i < collections.Length; i++) { if (collections[i].Count > 0) { AnyResult <T>?result = TryTakeFast(exclusiveSources, collections[i], i); if (result.HasValue) { return(new ValueTask <AnyResult <T> >(result.Value)); } } } // No luck during the fast route; just queue the rest of awaiters. for (int i = 0; i < collections.Length; i++) { AnyResult <T>?result = TryTakeFast(exclusiveSources, collections[i], i); if (result.HasValue) { return(new ValueTask <AnyResult <T> >(result.Value)); } } // None of the collections had any items. The order doesn't matter anymore, it's time to start the competition. exclusiveSources.UnlockCompetition(cancellationToken); return(new ValueTask <AnyResult <T> >(exclusiveSources.Task)); }
public bool Equals(AnyResult <T> other) => EqualityComparer <T> .Default.Equals(Value, other.Value) && EqualityComparer <int> .Default.Equals(CollectionIndex, other.CollectionIndex);