Просмотр исходного кода

[PLinq] Use a custom loop for iterating in ProcessAndAggregate to avoid the if cost at each round.

Jérémie Laval 15 лет назад
Родитель
Сommit
16e87dee36
1 измененных файлов с 17 добавлено и 15 удалено
  1. 17 15
      mcs/class/System.Core/System.Linq.Parallel/ParallelExecuter.cs

+ 17 - 15
mcs/class/System.Core/System.Linq.Parallel/ParallelExecuter.cs

@@ -167,25 +167,27 @@ namespace System.Linq.Parallel
 
 			for (int i = 0; i < tasks.Length; i++) {
 				int index = i;
-				bool firstRun = true;
 
 				tasks[i] = Task.Factory.StartNew (() => {
-					foreach (T item in enumerables[index]) {
-						// This is from specific operators
-						if (options.ImplementerToken.IsCancellationRequested)
-							break;
-						if (options.Token.IsCancellationRequested)
-							throw new OperationCanceledException (options.Token);
-
-						if (firstRun && seedFunc == null) {
-							firstRun = false;
-							// HACK: TODO: omgwtfitsuckssomuch
-							locals[index] = (U)(object)item;
-							continue;
+					var enumerator = enumerables[index].GetEnumerator ();
+					var token = options.Token;
+					var implementerToken = options.ImplementerToken;
+
+					try {
+						if (seedFunc == null) {
+							if (!enumerator.MoveNext ())
+								return;
+							locals[index] = (U)(object)enumerator.Current;
 						}
 						
-						U acc = locals[index];
-						locals[index] = localCall (acc, item);
+						while (enumerator.MoveNext ()) {
+							if (implementerToken.IsCancellationRequested)
+								break;
+							token.ThrowIfCancellationRequested ();
+							locals[index] = localCall (locals[index], enumerator.Current);
+						}
+					} finally {
+						enumerator.Dispose ();
 					}
 				}, options.Token);
 			}