private TaskResult ReadQueue(LazyQueue <TVal> queue) { var result = new TaskResult { Queue = queue }; TVal current; if (_ignoreFailures) { try { result.HasValue = queue.TryPeek(out current); } catch (Exception ex) { LogWarning(ex); current = default(TVal); } } else { result.HasValue = queue.TryPeek(out current); } result.Value = current; return(result); }
private IEnumerable <T> GetAggregateEnumerable() { // Used to pick the right element from each sub query in the right order var comparer = new OrderingComparer <T>(Expression); // Create lazy queues over each sub query so we can lazily pull items from it var lazyQueues = _subQueries.Select(query => new LazyQueue <T>(query.GetEnumerator())).ToList(); // Used to keep track of everything we've seen so far (we never show duplicates) var seen = new HashSet <T>(_equalityComparer); do { T minElement = default(T); LazyQueue <T> minQueue = null; // Run tasks in parallel var tasks = (from queue in lazyQueues select Task.Factory.StartNew(() => { T current; return(new { Empty = !queue.TryPeek(out current), Value = current, Queue = queue, }); })).ToArray(); // Wait for everything to complete Task.WaitAll(tasks); foreach (var task in tasks) { if (!task.Result.Empty) { // Keep track of the minimum element in the list if (minElement == null || comparer.Compare(task.Result.Value, minElement) < 0) { minElement = task.Result.Value; minQueue = task.Result.Queue; } } else { // Remove the enumerator if it's empty lazyQueues.Remove(task.Result.Queue); } } if (lazyQueues.Any()) { if (seen.Add(minElement)) { yield return(minElement); } // Clear the top of the enumerator we just peeked minQueue.Dequeue(); } } while (lazyQueues.Any()); }
/// <summary> /// Reads the minimal set of queries /// </summary> /// <param name="comparer"></param> /// <returns></returns> private IEnumerable <TVal> ReadOrderedQueues(IComparer <TVal> comparer) { // Create lazy queues over each sub query so we can lazily pull items from it var lazyQueues = _subQueries.Select(query => new LazyQueue <TVal>(query.GetEnumerator())).ToList(); // Used to keep track of everything we've seen so far (we never show duplicates) var seen = new HashSet <TVal>(_equalityComparer); do { TVal minElement = default(TVal); LazyQueue <TVal> minQueue = null; // Run tasks in parallel var tasks = (from queue in lazyQueues select Task.Factory.StartNew <TaskResult>(() => ReadQueue(queue)) ).ToArray(); // Wait for everything to complete Task.WaitAll(tasks); foreach (var task in tasks) { if (task.Result.HasValue) { // Keep track of the minimum element in the list if (minElement == null || comparer.Compare(task.Result.Value, minElement) < 0) { minElement = task.Result.Value; minQueue = task.Result.Queue; } } else { // Remove the enumerator if it's empty lazyQueues.Remove(task.Result.Queue); } } if (lazyQueues.Any()) { if (seen.Add(minElement)) { yield return(minElement); } // Clear the top of the enumerator we just peeked minQueue.Dequeue(); } } while (lazyQueues.Count > 0); }