Skip to content

Commit

Permalink
Add ThreadProxyRenderTimer (#12900)
Browse files Browse the repository at this point in the history
* Add ThreadProxyRenderTimer

* Forgot IsBackground

* Increase default stack size in ThreadProxyRenderTimer
  • Loading branch information
maxkatz6 authored Sep 15, 2023
1 parent 7b67fda commit 3619b80
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
70 changes: 70 additions & 0 deletions src/Avalonia.Base/Rendering/ThreadProxyRenderTimer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.Diagnostics;
using System.Threading;
using Avalonia.Metadata;

namespace Avalonia.Rendering;

[PrivateApi]
public sealed class ThreadProxyRenderTimer : IRenderTimer
{
private readonly IRenderTimer _inner;
private readonly Stopwatch _stopwatch;
private readonly Thread _timerThread;
private readonly AutoResetEvent _autoResetEvent;
private Action<TimeSpan>? _tick;
private int _subscriberCount;
private bool _registered;

public ThreadProxyRenderTimer(IRenderTimer inner, int maxStackSize = 1 * 1024 * 1024)
{
_inner = inner;
_stopwatch = new Stopwatch();
_autoResetEvent = new AutoResetEvent(false);
_timerThread = new Thread(RenderTimerThreadFunc, maxStackSize) { Name = "RenderTimerLoop", IsBackground = true };
}

public event Action<TimeSpan> Tick
{
add
{
_tick += value;

if (!_registered)
{
_registered = true;
_timerThread.Start();
}

if (_subscriberCount++ == 0)
{
_inner.Tick += InnerTick;
}
}

remove
{
if (--_subscriberCount == 0)
{
_inner.Tick -= InnerTick;
}

_tick -= value;
}
}

private void RenderTimerThreadFunc()
{
while (_autoResetEvent.WaitOne())
{
_tick?.Invoke(_stopwatch.Elapsed);
}
}

private void InnerTick(TimeSpan obj)
{
_autoResetEvent.Set();
}

public bool RunsInBackground => true;
}
2 changes: 1 addition & 1 deletion src/Avalonia.Native/AvaloniaNativePlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void DoInitialize(AvaloniaNativePlatformOptions options)
.Bind<IPlatformSettings>().ToConstant(new NativePlatformSettings(_factory.CreatePlatformSettings()))
.Bind<IWindowingPlatform>().ToConstant(this)
.Bind<IClipboard>().ToConstant(new ClipboardImpl(_factory.CreateClipboard()))
.Bind<IRenderTimer>().ToConstant(new AvaloniaNativeRenderTimer(_factory.CreatePlatformRenderTimer()))
.Bind<IRenderTimer>().ToConstant(new ThreadProxyRenderTimer(new AvaloniaNativeRenderTimer(_factory.CreatePlatformRenderTimer())))
.Bind<IMountedVolumeInfoProvider>().ToConstant(new MacOSMountedVolumeInfoProvider())
.Bind<IPlatformDragSource>().ToConstant(new AvaloniaNativeDragSource(_factory))
.Bind<IPlatformLifetimeEventsImpl>().ToConstant(applicationPlatform)
Expand Down

0 comments on commit 3619b80

Please sign in to comment.