Less raw loops.

pull/90/head
T 2020-06-11 00:07:05 -04:00
parent 95c93b7c3d
commit 5c9c4f5cac
2 changed files with 66 additions and 73 deletions

View File

@ -68,6 +68,55 @@ namespace Cysharp.Threading.Tasks.Internal
return (buffer, index);
}
}
public static void Swap<T>(IList<T> array, int indexA, int indexB)
{
var tmp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = tmp;
}
/// <summary>
/// Returns the index of the first element satisfying the <paramref name="predicate"/>.
/// Returns -1 if no such element exists.
/// </summary>
/// <param name="array">The array to search.</param>
/// <param name="predicate">The predicate use to search the array.</param>
/// <typeparam name="T">The type of elements in the array.</typeparam>
/// <returns>Index of the first element satisfying the <paramref name="predicate"/> otherwise returns -1.</returns>
public static int FirstIndexOf<T>(IReadOnlyList<T> array, Func<T, bool> predicate)
{
for (var i = 0; i < array.Count; ++i)
{
if (!predicate(array[i])) continue;
return i;
}
return -1;
}
/// <summary>
/// Reorders the elements in <paramref name="array"/> in such a way that all elements for which the <paramref name="predicate"/>
/// returns <c>true </c> precede the elements for which <paramref name="predicate"/> returns <c>false</c>.
/// Relative order of the elements is not preserved.
/// </summary>
/// <param name="array">The array to partition.</param>
/// <param name="predicate">The predicate that determine how the elements are partitioned.</param>
/// <typeparam name="T">The type of the elements in the array.</typeparam>
/// <returns>Return the index of first element of the second group.</returns>
public static int Partition<T>(T[] array, Func<T, bool> predicate)
{
var pivot = FirstIndexOf(array, element => !predicate(element));
if (pivot == -1) return array.Length;
for (var i = pivot + 1; i < array.Length; ++i)
{
if (!predicate(array[i])) continue;
Swap(array, pivot, i);
++pivot;
}
return pivot;
}
}
}

View File

@ -1,5 +1,4 @@

using System;
using System;
using UnityEngine;
namespace Cysharp.Threading.Tasks.Internal
@ -131,6 +130,7 @@ namespace Cysharp.Threading.Tasks.Internal
void PostLateUpdate() => RunCore();
void LastPostLateUpdate() => RunCore();
[System.Diagnostics.DebuggerHidden]
void RunCore()
{
@ -141,84 +141,28 @@ namespace Cysharp.Threading.Tasks.Internal
lock (arrayLock)
{
var j = tail - 1;
// eliminate array-bound check for i
for (int i = 0; i < loopItems.Length; i++)
{
var action = loopItems[i];
if (action != null)
var pivot = ArrayUtil.Partition(loopItems, playerLoopItem =>
{
try
{
if (!action.MoveNext())
return playerLoopItem != null && playerLoopItem.MoveNext();
}
catch (Exception e)
{
try
{
unhandledExceptionCallback(e);
return false;
}
catch
{
return false;
}
}
});
for (var i = pivot; i < loopItems.Length; ++i)
loopItems[i] = null;
}
else
{
continue; // next i
}
}
catch (Exception ex)
{
loopItems[i] = null;
try
{
unhandledExceptionCallback(ex);
}
catch { }
}
}
// find null, loop from tail
while (i < j)
{
var fromTail = loopItems[j];
if (fromTail != null)
{
try
{
if (!fromTail.MoveNext())
{
loopItems[j] = null;
j--;
continue; // next j
}
else
{
// swap
loopItems[i] = fromTail;
loopItems[j] = null;
j--;
goto NEXT_LOOP; // next i
}
}
catch (Exception ex)
{
loopItems[j] = null;
j--;
try
{
unhandledExceptionCallback(ex);
}
catch { }
continue; // next j
}
}
else
{
j--;
}
}
tail = i; // loop end
break; // LOOP END
NEXT_LOOP:
continue;
}
lock (runningAndQueueLock)
{