Skip to content

Commit

Permalink
netstandard2.0, 2.1, net6.0(WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Jan 4, 2024
1 parent 182f252 commit 8171a19
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 53 deletions.
13 changes: 13 additions & 0 deletions src/R3/Internal/Shims/CancellationTokenExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#if NETSTANDARD2_0 || NETSTANDARD2_1

namespace System.Threading;

internal static class CancellationTokenExtensions
{
public static CancellationTokenRegistration UnsafeRegister(this CancellationToken cancellationToken, Action<object?> callback, object? state)
{
return cancellationToken.Register(callback, state);
}
}

#endif
24 changes: 24 additions & 0 deletions src/R3/Internal/Shims/CollectionsMarshal.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Runtime.CompilerServices;

#if !NET6_0_OR_GREATER
namespace System.Runtime.InteropServices;

internal static class CollectionsMarshal
{
#pragma warning disable CS8618
#pragma warning disable CS0169
#pragma warning disable CS0649

class ListDummy<T>
{
public T[] Items;
int size;
int version;
}

internal static Span<T> AsSpan<T>(List<T> list)
{
return Unsafe.As<ListDummy<T>>(list).Items.AsSpan(0, list.Count);
}
}
#endif
19 changes: 19 additions & 0 deletions src/R3/Internal/Shims/StackTraceHidden.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#if NETSTANDARD2_0 || NETSTANDARD2_1

namespace System.Diagnostics
{
/// <summary>
/// Types and Methods attributed with StackTraceHidden will be omitted from the stack trace text shown in StackTrace.ToString()
/// and Exception.StackTrace
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct, Inherited = false)]
internal sealed class StackTraceHiddenAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="StackTraceHiddenAttribute"/> class.
/// </summary>
public StackTraceHiddenAttribute() { }
}
}

#endif
33 changes: 33 additions & 0 deletions src/R3/Internal/Shims/TaskExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#if NETSTANDARD2_0 || NETSTANDARD2_1

namespace R3;

internal static class TaskExtensions
{
internal static Task<T> WaitAsync<T>(this Task<T> task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<T>();
var registration = cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken));

task.ContinueWith(t =>
{
registration.Dispose();
if (t.IsFaulted)
{
tcs.TrySetException(t.Exception!.InnerExceptions);
}
else if (t.IsCanceled)
{
tcs.TrySetCanceled(cancellationToken);
}
else
{
tcs.TrySetResult(t.Result);
}
}, TaskScheduler.Default);

return tcs.Task;
}
}

#endif
27 changes: 27 additions & 0 deletions src/R3/Internal/Shims/ThreadPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#if NETSTANDARD2_0 || NETSTANDARD2_1

namespace R3 // namespace priority
{
public interface IThreadPoolWorkItem
{
void Execute();
}

public static class ThreadPool
{
static readonly WaitCallback waitCallback = Execute;

public static bool UnsafeQueueUserWorkItem(IThreadPoolWorkItem callBack, bool preferLocal)
{
return global::System.Threading.ThreadPool.UnsafeQueueUserWorkItem(waitCallback, callBack);
}

static void Execute(object? state)
{
var workItem = (IThreadPoolWorkItem)state!;
workItem.Execute();
}
}
}

#endif
3 changes: 2 additions & 1 deletion src/R3/Operators/AggregateOperators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@ public static Task<T> MaxAsync<T>(this Observable<T> source, CancellationToken c
}, cancellationToken);
}

#if NET8_0_OR_GREATER

public static Task<T> SumAsync<T>(this Observable<T> source, CancellationToken cancellationToken = default)
where T : IAdditionOperators<T, T, T>
{
return AggregateAsync(source, default(T)!, static (sum, message) => checked(sum + message), Stubs<T>.ReturnSelf, cancellationToken); // ignore complete
}


public static Task<double> AverageAsync<T>(this Observable<T> source, CancellationToken cancellationToken = default)
where T : INumberBase<T>
{
Expand All @@ -126,6 +126,7 @@ public static Task<double> AverageAsync<T>(this Observable<T> source, Cancellati
cancellationToken);
}

#endif

public static Task WaitAsync<T>(this Observable<T> source, CancellationToken cancellationToken = default)
{
Expand Down
4 changes: 2 additions & 2 deletions src/R3/Operators/ContainsAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ public static Task<bool> ContainsAsync<T>(this Observable<T> source, T value, IE
}
}

internal sealed class ContainsAsync<T>(T value, IEqualityComparer<T> equalityComparer, CancellationToken cancellationToken)
internal sealed class ContainsAsync<T>(T compareValue, IEqualityComparer<T> equalityComparer, CancellationToken cancellationToken)
: TaskObserverBase<T, bool>(cancellationToken)
{
protected override void OnNextCore(T value)
{
if (!equalityComparer.Equals(value))
if (!equalityComparer.Equals(value, compareValue))
{
TrySetResult(true);
}
Expand Down
9 changes: 9 additions & 0 deletions src/R3/Operators/ElementAtAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public static Task<T> ElementAtAsync<T>(this Observable<T> source, int index, Ca
return observer.Task;
}

#if !NETSTANDARD2_0

public static Task<T> ElementAtAsync<T>(this Observable<T> source, Index index, CancellationToken cancellationToken = default)
{
if (index.IsFromEnd)
Expand All @@ -26,6 +28,8 @@ public static Task<T> ElementAtAsync<T>(this Observable<T> source, Index index,
}
}

#endif

public static Task<T> ElementAtOrDefaultAsync<T>(this Observable<T> source, int index, T? defaultValue = default, CancellationToken cancellationToken = default)
{
if (index < 0) throw new ArgumentOutOfRangeException("index");
Expand All @@ -34,6 +38,8 @@ public static Task<T> ElementAtOrDefaultAsync<T>(this Observable<T> source, int
return observer.Task;
}

#if !NETSTANDARD2_0

public static Task<T> ElementAtOrDefaultAsync<T>(this Observable<T> source, Index index, T? defaultValue = default, CancellationToken cancellationToken = default)
{
if (index.IsFromEnd)
Expand All @@ -47,6 +53,9 @@ public static Task<T> ElementAtOrDefaultAsync<T>(this Observable<T> source, Inde
return ElementAtOrDefaultAsync(source, index.Value, defaultValue, cancellationToken);
}
}

#endif

}

internal sealed class ElementAtAsync<T>(int index, bool useDefaultValue, T? defaultValue, CancellationToken cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion src/R3/Operators/ObserveOn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ static void DrainMessages(object? state)
var self = (_ObserveOn)state!;
var queue = self.queue;

Notification<T> value;
Notification<T> value = default;
while (true)
{
lock (queue)
Expand Down
6 changes: 5 additions & 1 deletion src/R3/Operators/ToAsyncEnumerable.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Threading.Channels;
#if !NETSTANDARD2_0

using System.Threading.Channels;

namespace R3;

Expand Down Expand Up @@ -59,3 +61,5 @@ protected override void DisposeCore()
registration.Dispose();
}
}

#endif
2 changes: 1 addition & 1 deletion src/R3/Operators/ToLookupAsync.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Xml.Linq;
using System.Collections;

namespace R3;

Expand Down
87 changes: 43 additions & 44 deletions src/R3/R3.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFrameworks>netstandard2.0;netstandard2.1;net6.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

<GenerateDocumentationFile>true</GenerateDocumentationFile>
Expand All @@ -16,25 +17,23 @@

<ItemGroup>
<None Include="../../Icon.png" Pack="true" PackagePath="/" />
<None Include="Operators\CombineLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CombineLatest.tt</DependentUpon>
</None>
<None Include="Operators\Zip.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Zip.tt</DependentUpon>
</None>
<None Include="Operators\ZipLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ZipLatest.tt</DependentUpon>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'net6.0'">
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="8.0.0" />
</ItemGroup>

<ItemGroup Condition="$(TargetFramework) == 'netstandard2.0' Or $(TargetFramework) == 'netstandard2.1'">
<PackageReference Include="Microsoft.Bcl.TimeProvider" Version="8.0.0" />
<PackageReference Include="System.Threading.Channels" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
Expand All @@ -43,40 +42,40 @@
</ItemGroup>

<ItemGroup>
<None Update="Operators\CombineLatest.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>CombineLatest.cs</LastGenOutput>
</None>
<None Update="Operators\Zip.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Zip.cs</LastGenOutput>
</None>
<None Update="Operators\ZipLatest.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ZipLatest.cs</LastGenOutput>
</None>
<None Update="Operators\CombineLatest.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>CombineLatest.cs</LastGenOutput>
</None>
<None Update="Operators\Zip.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Zip.cs</LastGenOutput>
</None>
<None Update="Operators\ZipLatest.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ZipLatest.cs</LastGenOutput>
</None>
</ItemGroup>

<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>

<ItemGroup>
<Compile Update="Operators\CombineLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CombineLatest.tt</DependentUpon>
</Compile>
<Compile Update="Operators\Zip.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Zip.tt</DependentUpon>
</Compile>
<Compile Update="Operators\ZipLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ZipLatest.tt</DependentUpon>
</Compile>
<Compile Update="Operators\CombineLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>CombineLatest.tt</DependentUpon>
</Compile>
<Compile Update="Operators\Zip.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Zip.tt</DependentUpon>
</Compile>
<Compile Update="Operators\ZipLatest.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ZipLatest.tt</DependentUpon>
</Compile>
</ItemGroup>

</Project>
5 changes: 2 additions & 3 deletions src/R3/SubscriptionTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ public static void ForEachActiveTask(Action<TrackingState> action)
lock (iterateCache)
{
var count = tracking.CaptureSnapshot(ref iterateCache, clear: false);
var span = CollectionsMarshal.AsSpan(iterateCache).Slice(0, count);
span.Sort();
iterateCache.Sort(0, count, Comparer<TrackingState>.Default);
try
{
for (int i = 0; i < count; i++)
Expand All @@ -103,7 +102,7 @@ public static void ForEachActiveTask(Action<TrackingState> action)
}
finally
{
span.Clear();
iterateCache.Clear();
}
}
}
Expand Down

0 comments on commit 8171a19

Please sign in to comment.