// Needed for NET40 #if !NET_4_6 using System; using System.Globalization; using LinqInternal.Core; namespace LinqInternal.Threading.Needles { [System.Diagnostics.DebuggerNonUserCode] internal static class NeedleHelper { public static bool CanCreateDeferredNeedle() where TNeedle : INeedle { return DeferredNeedleCreator.CanCreate; } public static bool CanCreateDeferredReadOnlyNeedle() where TNeedle : IReadOnlyNeedle { return DeferredReadOnlyNeedleCreator.CanCreate; } public static bool CanCreateNeedle() where TNeedle : INeedle { return NeedleCreator.CanCreate; } public static bool CanCreateNestedNeedle() where TNeedle : INeedle { return NestedNeedleCreator.CanCreate; } public static bool CanCreateNestedReadOnlyNeedle() where TNeedle : IReadOnlyNeedle { return NestedReadOnlyNeedleCreator.CanCreate; } public static bool CanCreateReadOnlyNeedle() where TNeedle : IReadOnlyNeedle { return ReadOnlyNeedleCreator.CanCreate; } public static TNeedle CreateDeferredNeedle(Func target) where TNeedle : INeedle { return DeferredNeedleCreator.Create(target); } public static TNeedle CreateDeferredReadOnlyNeedle(Func target) where TNeedle : IReadOnlyNeedle { return DeferredReadOnlyNeedleCreator.Create(target); } public static TNeedle CreateNeedle(T target) where TNeedle : INeedle { return NeedleCreator.Create(target); } public static TNeedle CreateNestedNeedle(INeedle target) where TNeedle : INeedle { return NestedNeedleCreator.Create(target); } public static TNeedle CreateReadOnlyNeedle(T target) where TNeedle : IReadOnlyNeedle { return ReadOnlyNeedleCreator.Create(target); } public static TNeedle CreateReadOnlyNestedNeedle(IReadOnlyNeedle target) where TNeedle : IReadOnlyNeedle { return NestedReadOnlyNeedleCreator.Create(target); } public static bool Retrieve(this TNeedle needle, out T target) where TNeedle : IRecyclableNeedle { if (ReferenceEquals(needle, null)) { target = default(T); return false; } bool done; var cacheNeedle = needle as ICacheNeedle; if (cacheNeedle == null) { target = ((INeedle)needle).Value; done = needle.IsAlive; } else { done = cacheNeedle.TryGetValue(out target); } if (done) { needle.Free(); } return done; } public static bool TryGetValue(this IReadOnlyNeedle needle, out T target) { if (needle == null) { target = default(T); return false; } var cacheNeedle = needle as ICacheNeedle; if (cacheNeedle != null) { return cacheNeedle.TryGetValue(out target); } target = ((INeedle)needle).Value; return needle.IsAlive; } private static class DeferredNeedleCreator where TNeedle : INeedle { private static readonly bool _canCreate; private static readonly Func, TNeedle> _create; static DeferredNeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func tmpA; _canCreate = TypeHelper.TryGetCreate(out tmpA); if (_canCreate) { _create = target => tmpA(target.Invoke()); } else { Func tmpB; _canCreate = TypeHelper.TryGetCreate(out tmpB); if (_canCreate) { _create = target => { var needle = tmpB.Invoke(); needle.Value = target.Invoke(); return needle; }; } } } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(Func target) { return _create.Invoke(target); } } private static class DeferredReadOnlyNeedleCreator where TNeedle : IReadOnlyNeedle { private static readonly bool _canCreate; private static readonly Func, TNeedle> _create; static DeferredReadOnlyNeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func tmp; _canCreate = TypeHelper.TryGetCreate(out tmp); if (_canCreate) { _create = target => tmp(target.Invoke()); } } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(Func target) { return _create.Invoke(target); } } private static class NeedleCreator where TNeedle : INeedle { private static readonly bool _canCreate; private static readonly Func _create; static NeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func tmpA; _canCreate = TypeHelper.TryGetCreate(out tmpA); if (_canCreate) { _create = target => { var needle = tmpA.Invoke(); needle.Value = target; return needle; }; } else { Func, TNeedle> tmpB; _canCreate = TypeHelper.TryGetCreate(out tmpB); if (_canCreate) { _create = target => tmpB(() => target); } } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(T target) { return _create.Invoke(target); } } private static class NestedNeedleCreator where TNeedle : INeedle { private static readonly bool _canCreate; private static readonly Func, TNeedle> _create; static NestedNeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func>, TNeedle> tmp; _canCreate = TypeHelper.TryGetCreate(out tmp); if (_canCreate) { _create = target => tmp(() => target); } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(INeedle target) { return _create.Invoke(target); } } private static class NestedReadOnlyNeedleCreator where TNeedle : IReadOnlyNeedle { private static readonly bool _canCreate; private static readonly Func, TNeedle> _create; static NestedReadOnlyNeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func>, TNeedle> tmp; _canCreate = TypeHelper.TryGetCreate(out tmp); if (_canCreate) { _create = target => tmp(() => target); } } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(IReadOnlyNeedle target) { return _create.Invoke(target); } } private static class ReadOnlyNeedleCreator where TNeedle : IReadOnlyNeedle { private static readonly bool _canCreate; private static readonly Func _create; static ReadOnlyNeedleCreator() { _canCreate = TypeHelper.TryGetCreate(out _create); if (!_canCreate) { Func, TNeedle> tmp; _canCreate = TypeHelper.TryGetCreate(out tmp); if (_canCreate) { _create = target => tmp(() => target); } } if (!_canCreate) { _create = _ => { throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to find a way to create {0}", typeof(TNeedle).Name)); }; } } public static bool CanCreate { get { return _canCreate; } } public static TNeedle Create(T target) { return _create.Invoke(target); } } } } #endif