Skip to content

Commit

Permalink
EveryUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Dec 14, 2023
1 parent 8a6ccf0 commit a76fbe9
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 94 deletions.
88 changes: 88 additions & 0 deletions src/R3/Factories/EveryUpdate.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
namespace R3;

public static partial class Event
{
public static Event<Unit> EveryUpdate()
{
return new EveryUpdate(EventSystem.DefaultFrameProvider, CancellationToken.None, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(CancellationToken cancellationToken)
{
return new EveryUpdate(EventSystem.DefaultFrameProvider, cancellationToken, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider)
{
return new EveryUpdate(frameProvider, CancellationToken.None, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken)
{
return new EveryUpdate(frameProvider, cancellationToken, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken, bool cancelImmediately)
{
return new EveryUpdate(frameProvider, cancellationToken, cancelImmediately: cancelImmediately);
}
}


internal sealed class EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken, bool cancelImmediately) : Event<Unit>
{
protected override IDisposable SubscribeCore(Subscriber<Unit> subscriber)
{
var runner = new EveryUpdateRunnerWorkItem(subscriber, cancellationToken, cancelImmediately);
frameProvider.Register(runner);
return runner;
}

class EveryUpdateRunnerWorkItem : IFrameRunnerWorkItem, IDisposable
{
Subscriber<Unit> subscriber;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool isDisposed;

public EveryUpdateRunnerWorkItem(Subscriber<Unit> subscriber, CancellationToken cancellationToken, bool cancelImmediately)
{
this.subscriber = subscriber;
this.cancellationToken = cancellationToken;

if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.UnsafeRegister(static state =>
{
var s = (EveryUpdateRunnerWorkItem)state!;
s.subscriber.OnCompleted();
s.Dispose();
}, this);
}
}

public bool MoveNext(long frameCount)
{
if (isDisposed)
{
return false;
}

if (cancellationToken.IsCancellationRequested)
{
subscriber.OnCompleted();
Dispose();
return false;
}

subscriber.OnNext(default);
return true;
}

public void Dispose()
{
isDisposed = true;
cancellationTokenRegistration.Dispose();
}
}
}
86 changes: 1 addition & 85 deletions src/R3/Factories/_EventFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,89 +28,5 @@ public static partial class Event
// AsNeverComplete

// TODO: use SystemDefault

public static Event<Unit> EveryUpdate()
{
return new EveryUpdate(EventSystem.DefaultFrameProvider, CancellationToken.None, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(CancellationToken cancellationToken)
{
return new EveryUpdate(EventSystem.DefaultFrameProvider, cancellationToken, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider)
{
return new EveryUpdate(frameProvider, CancellationToken.None, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken)
{
return new EveryUpdate(frameProvider, cancellationToken, cancelImmediately: false);
}

public static Event<Unit> EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken, bool cancelImmediately)
{
return new EveryUpdate(frameProvider, cancellationToken, cancelImmediately: cancelImmediately);
}
}



internal sealed class EveryUpdate(FrameProvider frameProvider, CancellationToken cancellationToken, bool cancelImmediately) : Event<Unit>
{
protected override IDisposable SubscribeCore(Subscriber<Unit> subscriber)
{
var runner = new EveryUpdateRunnerWorkItem(subscriber, cancellationToken, cancelImmediately);
frameProvider.Register(runner);
return runner;
}

class EveryUpdateRunnerWorkItem : IFrameRunnerWorkItem, IDisposable
{
Subscriber<Unit> subscriber;
CancellationToken cancellationToken;
CancellationTokenRegistration cancellationTokenRegistration;
bool isDisposed;

public EveryUpdateRunnerWorkItem(Subscriber<Unit> subscriber, CancellationToken cancellationToken, bool cancelImmediately)
{
this.subscriber = subscriber;
this.cancellationToken = cancellationToken;

if (cancelImmediately && cancellationToken.CanBeCanceled)
{
cancellationTokenRegistration = cancellationToken.UnsafeRegister(static state =>
{
var s = (EveryUpdateRunnerWorkItem)state!;
s.subscriber.OnCompleted();
s.Dispose();
}, this);
}
}

public bool MoveNext(long frameCount)
{
if (isDisposed)
{
return false;
}

if (cancellationToken.IsCancellationRequested)
{
subscriber.OnCompleted();
Dispose();
return false;
}

subscriber.OnNext(default);
return true;
}

public void Dispose()
{
isDisposed = true;
cancellationTokenRegistration.Dispose();
}
}

}
8 changes: 7 additions & 1 deletion src/R3/FrameProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ public interface IFrameRunnerWorkItem
public sealed class ManualFrameProvider : FrameProvider
{
long frameCount;
FreeListCore<IFrameRunnerWorkItem> list = new FreeListCore<IFrameRunnerWorkItem>();
readonly object gate = new object();
FreeListCore<IFrameRunnerWorkItem> list;

public ManualFrameProvider()
{
list = new FreeListCore<IFrameRunnerWorkItem>(gate);
}

public override long GetFrameCount()
{
Expand Down
2 changes: 1 addition & 1 deletion tests/R3.Tests/FactoryTests/EmptyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void EmptyWithTime()
using var list = Event.Empty<int>(TimeSpan.FromSeconds(5), fakeTime).ToLiveList();

fakeTime.Advance(TimeSpan.FromSeconds(4));
list.AssertIsNoResulted();
list.AssertIsNotCompleted();

fakeTime.Advance(TimeSpan.FromSeconds(1));
list.AssertIsCompleted();
Expand Down
71 changes: 71 additions & 0 deletions tests/R3.Tests/FactoryTests/EveryUpdateTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
namespace R3.Tests.FactoryTests;

public class EveryUpdateTest
{
[Fact]
public void EveryUpdate()
{
var cts = new CancellationTokenSource();
var frameProvider = new ManualFrameProvider();

var list = Event.EveryUpdate(frameProvider, cts.Token).Select(_ => frameProvider.GetFrameCount()).ToLiveList();

list.AssertEqual([]);

frameProvider.Advance();
list.AssertEqual([0]);

frameProvider.Advance(3);
list.AssertEqual([0, 1, 2, 3]);

cts.Cancel();
list.AssertIsNotCompleted();

frameProvider.Advance();
list.AssertIsCompleted();
}

[Fact]
public void EveryUpdateCancelImmediate()
{
var cts = new CancellationTokenSource();
var frameProvider = new ManualFrameProvider();

var list = Event.EveryUpdate(frameProvider, cts.Token, cancelImmediately: true).Select(_ => frameProvider.GetFrameCount()).ToLiveList();

list.AssertEqual([]);

frameProvider.Advance();
list.AssertEqual([0]);

frameProvider.Advance(3);
list.AssertEqual([0, 1, 2, 3]);

cts.Cancel();
list.AssertIsCompleted();

frameProvider.Advance();
list.AssertEqual([0, 1, 2, 3]);
list.AssertIsCompleted();
}

[Fact]
public void EveryUpdateDispose()
{
var frameProvider = new ManualFrameProvider();

var list = Event.EveryUpdate(frameProvider).Select(_ => frameProvider.GetFrameCount()).ToLiveList();

list.AssertEqual([]);

frameProvider.Advance();
list.AssertEqual([0]);

frameProvider.Advance(3);
list.AssertEqual([0, 1, 2, 3]);

list.Dispose();
frameProvider.Advance();
list.AssertEqual([0, 1, 2, 3]);
}
}
2 changes: 1 addition & 1 deletion tests/R3.Tests/FactoryTests/ReturnOnCompletedTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void ReturnOnCompleted()

fakeTime.Advance(TimeSpan.FromSeconds(4));
list.AssertEqual([]);
list.AssertIsNoResulted();
list.AssertIsNotCompleted();

fakeTime.Advance(TimeSpan.FromSeconds(1));
list.AssertEqual([]);
Expand Down
4 changes: 2 additions & 2 deletions tests/R3.Tests/FactoryTests/ReturnTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void Return()

fakeTime.Advance(TimeSpan.FromSeconds(4));
list.AssertEqual([]);
list.AssertIsNoResulted();
list.AssertIsNotCompleted();

fakeTime.Advance(TimeSpan.FromSeconds(1));
list.AssertEqual([10]);
Expand Down Expand Up @@ -63,7 +63,7 @@ public void ReturnOnCompleted()

fakeTime.Advance(TimeSpan.FromSeconds(4));
list.AssertEqual([]);
list.AssertIsNoResulted();
list.AssertIsNotCompleted();

fakeTime.Advance(TimeSpan.FromSeconds(1));
list.AssertEqual([10]);
Expand Down
2 changes: 1 addition & 1 deletion tests/R3.Tests/FactoryTests/ThrowTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void Throw()

fakeTime.Advance(TimeSpan.FromSeconds(4));
list.AssertEqual([]);
list.AssertIsNoResulted();
list.AssertIsNotCompleted();

fakeTime.Advance(TimeSpan.FromSeconds(1));
list.AssertEqual([]);
Expand Down
4 changes: 2 additions & 2 deletions tests/R3.Tests/OperatorTests/WhereTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void WhereCompletable()
p.PublishOnNext(30);
list.AssertEqual([1, 3]);

list.AssertIsNoResulted();
list.AssertIsNotCompleted();

p.PublishOnCompleted(default);

Expand Down Expand Up @@ -84,7 +84,7 @@ public void WhereCompletableIndexed()
p.PublishOnNext(8);
list.AssertEqual([1, 5, 8]);

list.AssertIsNoResulted();
list.AssertIsNotCompleted();

p.PublishOnCompleted(default);

Expand Down
2 changes: 1 addition & 1 deletion tests/R3.Tests/_TestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public static void AssertIsCompleted<T>(this LiveList<T> list)
list.IsCompleted.Should().BeTrue();
}

public static void AssertIsNoResulted<T>(this LiveList<T> list)
public static void AssertIsNotCompleted<T>(this LiveList<T> list)
{
list.IsCompleted.Should().BeFalse();
}
Expand Down

0 comments on commit a76fbe9

Please sign in to comment.