Merge pull request #17 from mlemanczyk/codex/add-optimized-addrange-methods
Add optimized AddRange overloads
This commit is contained in:
4 files changed
+148
No files matched your search
@@ -401,5 +401,6 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,80 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
public static class zRecyclableListAddRange
|
public static class zRecyclableListAddRange
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static class AddRangeHelper<T>
|
||||||
|
{
|
||||||
|
private static readonly Action<RecyclableList<T>, object>? _dictionaryAdder;
|
||||||
|
private static readonly Action<RecyclableList<T>, object>? _sortedListAdder;
|
||||||
|
private static readonly Type? _dictionaryType;
|
||||||
|
private static readonly Type? _sortedListType;
|
||||||
|
|
||||||
|
static AddRangeHelper()
|
||||||
|
{
|
||||||
|
Type elementType = typeof(T);
|
||||||
|
if (elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
|
||||||
|
{
|
||||||
|
Type[] args = elementType.GetGenericArguments();
|
||||||
|
_dictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args);
|
||||||
|
MethodInfo? method = typeof(zRecyclableListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
binder: null,
|
||||||
|
types: new[] { typeof(RecyclableList<>).MakeGenericType(elementType), _dictionaryType },
|
||||||
|
modifiers: null);
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableList<T>));
|
||||||
|
var objParam = Expression.Parameter(typeof(object));
|
||||||
|
var call = Expression.Call(method, listParam, Expression.Convert(objParam, _dictionaryType));
|
||||||
|
_dictionaryAdder = Expression.Lambda<Action<RecyclableList<T>, object>>(call, listParam, objParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(ValueTuple<,>))
|
||||||
|
{
|
||||||
|
Type[] args = elementType.GetGenericArguments();
|
||||||
|
_sortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args);
|
||||||
|
MethodInfo? method = typeof(zRecyclableListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
binder: null,
|
||||||
|
types: new[] { typeof(RecyclableList<>).MakeGenericType(elementType), _sortedListType },
|
||||||
|
modifiers: null);
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableList<T>));
|
||||||
|
var objParam = Expression.Parameter(typeof(object));
|
||||||
|
var call = Expression.Call(method, listParam, Expression.Convert(objParam, _sortedListType));
|
||||||
|
_sortedListAdder = Expression.Lambda<Action<RecyclableList<T>, object>>(call, listParam, objParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool TryAddRange(RecyclableList<T> list, IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
if (_dictionaryAdder != null && _dictionaryType!.IsInstanceOfType(items))
|
||||||
|
{
|
||||||
|
_dictionaryAdder(list, items);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sortedListAdder != null && _sortedListType!.IsInstanceOfType(items))
|
||||||
|
{
|
||||||
|
_sortedListAdder(list, items);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
||||||
{
|
{
|
||||||
var enumerator = items.GetEnumerator();
|
var enumerator = items.GetEnumerator();
|
||||||
@@ -577,6 +646,9 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
AddRange(list, sourceQueue);
|
AddRange(list, sourceQueue);
|
||||||
}
|
}
|
||||||
|
else if (AddRangeHelper<T>.TryAddRange(list, items))
|
||||||
|
{
|
||||||
|
}
|
||||||
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
||||||
{
|
{
|
||||||
AddRange(list, sourceIReadOnlyList);
|
AddRange(list, sourceIReadOnlyList);
|
||||||
|
|||||||
@@ -1,12 +1,81 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Reflection;
|
||||||
using Recyclable.Collections.Pools;
|
using Recyclable.Collections.Pools;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
public static class zRecyclableLongListAddRange
|
public static class zRecyclableLongListAddRange
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private static class AddRangeHelper<T>
|
||||||
|
{
|
||||||
|
private static readonly Action<RecyclableLongList<T>, object>? _dictionaryAdder;
|
||||||
|
private static readonly Action<RecyclableLongList<T>, object>? _sortedListAdder;
|
||||||
|
private static readonly Type? _dictionaryType;
|
||||||
|
private static readonly Type? _sortedListType;
|
||||||
|
|
||||||
|
static AddRangeHelper()
|
||||||
|
{
|
||||||
|
Type elementType = typeof(T);
|
||||||
|
if (elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
|
||||||
|
{
|
||||||
|
Type[] args = elementType.GetGenericArguments();
|
||||||
|
_dictionaryType = typeof(RecyclableDictionary<,>).MakeGenericType(args);
|
||||||
|
MethodInfo? method = typeof(zRecyclableLongListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
binder: null,
|
||||||
|
types: new[] { typeof(RecyclableLongList<>).MakeGenericType(elementType), _dictionaryType },
|
||||||
|
modifiers: null);
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableLongList<T>));
|
||||||
|
var objParam = Expression.Parameter(typeof(object));
|
||||||
|
var call = Expression.Call(method, listParam, Expression.Convert(objParam, _dictionaryType));
|
||||||
|
_dictionaryAdder = Expression.Lambda<Action<RecyclableLongList<T>, object>>(call, listParam, objParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(ValueTuple<,>))
|
||||||
|
{
|
||||||
|
Type[] args = elementType.GetGenericArguments();
|
||||||
|
_sortedListType = typeof(RecyclableSortedList<,>).MakeGenericType(args);
|
||||||
|
MethodInfo? method = typeof(zRecyclableLongListAddRange).GetMethod(
|
||||||
|
nameof(AddRange),
|
||||||
|
BindingFlags.NonPublic | BindingFlags.Static,
|
||||||
|
binder: null,
|
||||||
|
types: new[] { typeof(RecyclableLongList<>).MakeGenericType(elementType), _sortedListType },
|
||||||
|
modifiers: null);
|
||||||
|
if (method != null)
|
||||||
|
{
|
||||||
|
var listParam = Expression.Parameter(typeof(RecyclableLongList<T>));
|
||||||
|
var objParam = Expression.Parameter(typeof(object));
|
||||||
|
var call = Expression.Call(method, listParam, Expression.Convert(objParam, _sortedListType));
|
||||||
|
_sortedListAdder = Expression.Lambda<Action<RecyclableLongList<T>, object>>(call, listParam, objParam).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool TryAddRange(RecyclableLongList<T> list, IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
if (_dictionaryAdder != null && _dictionaryType!.IsInstanceOfType(items))
|
||||||
|
{
|
||||||
|
_dictionaryAdder(list, items);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_sortedListAdder != null && _sortedListType!.IsInstanceOfType(items))
|
||||||
|
{
|
||||||
|
_sortedListAdder(list, items);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddRangeEnumerated<T>(this RecyclableLongList<T> targetList, IEnumerable<T> items)
|
private static void AddRangeEnumerated<T>(this RecyclableLongList<T> targetList, IEnumerable<T> items)
|
||||||
{
|
{
|
||||||
using IEnumerator<T> enumerator = items.GetEnumerator();
|
using IEnumerator<T> enumerator = items.GetEnumerator();
|
||||||
@@ -439,6 +508,11 @@ namespace Recyclable.Collections
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (AddRangeHelper<T>.TryAddRange(targetList, items))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity))
|
if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity))
|
||||||
{
|
{
|
||||||
targetList.AddRangeWithKnownCount(items, requiredAdditionalCapacity);
|
targetList.AddRangeWithKnownCount(items, requiredAdditionalCapacity);
|
||||||
|
|||||||
@@ -276,5 +276,6 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user