XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Threading;
using XFESystem.Desktop;

namespace XFESystem.Kernel;

/// <summary>One verified worker and sixteen pending callbacks; never holds a lock across application work.</summary>
internal sealed class NativeManagedWorkScheduler : IEditorBackgroundWorkScheduler, IEditorPreparationCanvasFactory
{
    // Both real UI and interpreter work retain the previous generous boot-stack
    // budget. Smaller managed stacks are not claimed safe without native proof.
    internal const int StackBytes = 8 * 1024 * 1024;
    private const int Capacity = 16;
    private readonly Action?[] pending = new Action?[Capacity];
    private uint published, consumed;
    private readonly Action<string> trace;
    private readonly Thread thread;
    private readonly int layoutScale;
    internal NativeManagedWorkScheduler(Action<string> trace, int layoutScale)
    {
        if (!NativeThreadRegression.Passed) throw new InvalidOperationException("The native thread/EH/GC regression has not passed.");
        this.trace = trace;
        this.layoutScale = layoutScale;
        thread = new Thread(WorkLoop, StackBytes);
        thread.Start();
    }
    public bool TryQueue(Action work)
    {
        ArgumentNullException.ThrowIfNull(work);
        // Single producer (the desktop) / single consumer. Publication is the
        // only shared operation; the worker never executes under a queue lock.
        uint writer = Volatile.Read(ref published), reader = Volatile.Read(ref consumed);
        if (unchecked(writer - reader) >= Capacity) return false;
        pending[writer & (Capacity - 1)] = work;
        Volatile.Write(ref published, unchecked(writer + 1));
        return true;
    }
    private void WorkLoop()
    {
        trace("XFE_EDITOR_WORKER_READY|Thread|" + NativeThreadRegression.CurrentThreadId() + "|StackBytes|" + StackBytes + "|SingleCpu|1|GcStopTheWorld|1|QueueCapacity|" + Capacity + "\n");
        while (true)
        {
            uint reader = Volatile.Read(ref consumed);
            if (reader == Volatile.Read(ref published)) { Thread.Sleep(2); continue; }
            var action = pending[reader & (Capacity - 1)]!;
            pending[reader & (Capacity - 1)] = null;
            Volatile.Write(ref consumed, unchecked(reader + 1));
            try { action(); }
            catch (Exception error) when (error is not OutOfMemoryException and not StackOverflowException)
            { trace("XFE_EDITOR_WORKER_UNHANDLED|" + error.GetType().Name + "\n"); }
        }
    }
    public IDesktopCanvas CreateEditorPreparationCanvas() => CanvasAdapter.CreateEditorPreparation(layoutScale);
}