Browse Source

Added some threading checks

pull/9718/head
Nikita Tsukanov 4 years ago
parent
commit
cbb42d756c
  1. 39
      src/Avalonia.Base/Rendering/Composition/CompositionCustomVisualHandler.cs
  2. 19
      src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs

39
src/Avalonia.Base/Rendering/Composition/CompositionCustomVisualHandler.cs

@ -21,16 +21,45 @@ public abstract class CompositionCustomVisualHandler
public abstract void OnRender(ImmediateDrawingContext drawingContext);
protected Vector2 EffectiveSize => _host?.Size ?? default;
void VerifyAccess()
{
if (_host == null)
throw new InvalidOperationException("Object is not yet attached to the compositor");
_host.Compositor.VerifyAccess();
}
protected Vector2 EffectiveSize
{
get
{
VerifyAccess();
return _host!.Size;
}
}
protected TimeSpan CompositionNow
{
get
{
VerifyAccess();
return _host!.Compositor.ServerNow;
}
}
protected TimeSpan CompositionNow => _host?.Compositor.ServerNow ?? default;
public virtual Rect GetRenderBounds() =>
new(0, 0, EffectiveSize.X, EffectiveSize.Y);
internal void Attach(ServerCompositionCustomVisual visual) => _host = visual;
protected void Invalidate() => _host?.HandlerInvalidate();
protected void Invalidate()
{
VerifyAccess();
_host!.HandlerInvalidate();
}
protected void RegisterForNextAnimationFrameUpdate() => _host?.HandlerRegisterForNextAnimationFrameUpdate();
protected void RegisterForNextAnimationFrameUpdate()
{
VerifyAccess();
_host!.HandlerRegisterForNextAnimationFrameUpdate();
}
}

19
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositor.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Avalonia.Logging;
using Avalonia.Platform;
using Avalonia.Rendering.Composition.Animations;
@ -31,6 +32,7 @@ namespace Avalonia.Rendering.Composition.Server
internal BatchStreamObjectPool<object?> BatchObjectPool;
internal BatchStreamMemoryPool BatchMemoryPool;
private object _lock = new object();
private Thread? _safeThread;
public PlatformRenderInterfaceContextManager RenderInterface { get; }
internal static readonly object RenderThreadJobsStartMarker = new();
internal static readonly object RenderThreadJobsEndMarker = new();
@ -129,7 +131,15 @@ namespace Avalonia.Rendering.Composition.Server
{
lock (_lock)
{
RenderCore();
try
{
_safeThread = Thread.CurrentThread;
RenderCore();
}
finally
{
_safeThread = null;
}
}
}
@ -180,5 +190,12 @@ namespace Avalonia.Rendering.Composition.Server
using (RenderInterface.EnsureCurrent())
return RenderInterface.CreateRenderTarget(surfaces);
}
public bool CheckAccess() => _safeThread == Thread.CurrentThread;
public void VerifyAccess()
{
if (!CheckAccess())
throw new InvalidOperationException("This object can be only accessed under compositor lock");
}
}
}

Loading…
Cancel
Save