Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniil Korostelev committed Jun 21, 2024
1 parent 6f769d6 commit 939395e
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 19 deletions.
62 changes: 44 additions & 18 deletions playground/Playground.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,61 @@
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using TinkState;
using Timer = System.Timers.Timer;

class Playground
{
static async Task Main()
static void Main()
{
var stateA = Observable.State("hello");
var stateB = Observable.State("world");
var time = CreateTimeObservable();
var o = Observable.Auto(() => (time.Value, time.Value.ToShortTimeString()));
// var o = time;

var o = Observable.Auto(async () =>
Console.WriteLine(o.Value);
Thread.Sleep(2000);
Console.WriteLine(o.Value);
//
// var counter = 0;
// IDisposable binding = null;
// binding = o.Bind(v =>
// {
// Console.WriteLine($"Current time is: {v}");
// counter++;
// if (counter >= 5) binding.Dispose();
// });

Process.GetCurrentProcess().WaitForExit();
}

private static Observable<DateTime> CreateTimeObservable()
{
var time = Observable.External(() => DateTime.UtcNow);

var timer = new Timer(1000);

var timerElapsedHandler = new ElapsedEventHandler((_, _) =>
{
Console.WriteLine("computing");
var a = stateA.Value;
await Task.Delay(1000);
var b = stateB.Value;
return a + " " + b;
Console.WriteLine("tick");
time.Invalidate();
});

o.Bind(result => Console.WriteLine(result.Status switch
time.Subscribed += () =>
{
AsyncComputeStatus.Loading => "Loading...",
AsyncComputeStatus.Done => "Done: " + result.Result,
AsyncComputeStatus.Failed => "Failed: " + result.Exception,
}));

await Task.Delay(1500);
Console.WriteLine("wakeup");
timer.Elapsed += timerElapsedHandler;
timer.Start();
};

stateB.Value = "Dan";
time.Unsubscribed += () =>
{
Console.WriteLine("sleep");
timer.Elapsed -= timerElapsedHandler;
timer.Stop();
};

Process.GetCurrentProcess().WaitForExit();
return time;
}
}
11 changes: 11 additions & 0 deletions src/TinkState/Runtime/ExternalObservableSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace TinkState
{
public interface ExternalObservableSource<out T> : Observable<T>
{
event Action Subscribed;
event Action Unsubscribed;
void Invalidate();
}
}
91 changes: 91 additions & 0 deletions src/TinkState/Runtime/Internal/ExternalObservableSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace TinkState.Internal
{
class ExternalObservableSource<T> : Dispatcher, TinkState.ExternalObservableSource<T>, DispatchingObservable<T>
{
public event Action Subscribed;
public event Action Unsubscribed;

readonly Func<T> getter;
readonly IEqualityComparer<T> comparer;

bool isSubscribedTo;
bool valid;
T last;

public ExternalObservableSource(Func<T> getter, IEqualityComparer<T> comparer)
{
this.getter = getter;
this.comparer = comparer ?? EqualityComparer<T>.Default;
}

public IDisposable Bind(Action<T> callback, IEqualityComparer<T> comparer = null, Scheduler scheduler = null)
{
return new Binding<T>(this, callback, comparer, scheduler);
}

public Observable<TOut> Map<TOut>(Func<T, TOut> transform, IEqualityComparer<TOut> comparer = null)
{
return new TransformObservable<T, TOut>(this, transform, comparer);
}

public IEqualityComparer<T> GetComparer()
{
return comparer;
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public T Value => AutoObservable.Track(this);

public void Invalidate()
{
if (valid)
{
valid = false;
Fire();
}
}

public T GetCurrentValue()
{
if (!valid || !isSubscribedTo)
{
Calculate();
}
return last;
}

public long GetRevision()
{
// TODO: auto-observables rely on this so what should we do?
return revision;
}

void Calculate()
{
last = getter();
valid = true;
}

protected override void OnStatusChange(bool active)
{
if (active) WakeUp(); else Sleep();
}

void WakeUp()
{
isSubscribedTo = true;
Calculate();
Subscribed?.Invoke();
}

void Sleep()
{
isSubscribedTo = false;
Unsubscribed?.Invoke();
}
}
}
7 changes: 6 additions & 1 deletion src/TinkState/Runtime/Observable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ public static State<T> State<T>(T initialValue, IEqualityComparer<T> comparer =
return new Internal.State<T>(initialValue, comparer);
}

public static ExternalObservableSource<T> External<T>(Func<T> getter, IEqualityComparer<T> comparer = null)
{
return new Internal.ExternalObservableSource<T>(getter, comparer);
}

/// <summary>
/// Create an empty observable list.
/// </summary>
Expand Down Expand Up @@ -220,4 +225,4 @@ public static ObservableDictionary<TKey, TValue> Dictionary<TKey, TValue>()
/// </remarks>
public static Scheduler Scheduler = Scheduler.Direct;
}
}
}

0 comments on commit 939395e

Please sign in to comment.