Files
sharpemu/src/SharpEmu.HLE/HostMainThread.cs
T
Berk 2b6bd5a532 Sdl backend (#670)
* [audio] added sdl audio backend and in-tree atrac9 decoder

* [input] replaced per-platform pad readers with sdl gamepad input

* [video] added sdl window and host display plumbing

* [gui] added host display options and per-game render settings

* [bink] synced host movie playback to the guest audio clock

* [cpu] hooked windows write faults into guest image tracking

* [perf] added guest and render profiling, reserved host cpu lanes

* [kernel] fixed stale pthread mutex handle alias

* [host] wired the sdl session, save-data paths and project references

* [audio] hoisted ajm trace stackalloc out of its loop

* [video] Add guest image sync setting

* [build] Strip native symbols

* reuse
2026-07-28 03:33:26 +03:00

79 lines
2.3 KiB
C#

// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using System.Collections.Concurrent;
namespace SharpEmu.HLE;
/// <summary>
/// Runs work on the real process main thread. macOS requires its windowing
/// event loop on that thread, so the CLI moves emulation onto
/// a worker thread, parks the main thread in <see cref="Pump"/>, and the
/// video presenter posts its window loop here. On other platforms
/// <see cref="IsAvailable"/> stays false and nothing changes.
/// </summary>
public static class HostMainThread
{
private static readonly BlockingCollection<Action> _work = new();
private static Action? _shutdownRequestHandler;
public static bool IsAvailable { get; private set; }
/// <summary>
/// Registers a callback invoked by <see cref="Shutdown"/> so a
/// long-running posted work item (the presenter's window loop) can be
/// asked to return to the pump.
/// </summary>
public static void SetShutdownRequestHandler(Action handler) =>
_shutdownRequestHandler = handler;
/// <summary>Marks the pump as present. Call before guest code can run.</summary>
public static void Enable() => IsAvailable = true;
public static void Post(Action work)
{
try
{
_work.Add(work);
}
catch (InvalidOperationException)
{
// Shutdown already requested; the process is exiting.
}
}
/// <summary>
/// Services posted work on the calling (main) thread until
/// <see cref="Shutdown"/> is called and the queue drains.
/// </summary>
public static void Pump()
{
foreach (var work in _work.GetConsumingEnumerable())
{
try
{
work();
}
catch (Exception exception)
{
Console.Error.WriteLine($"[LOADER][ERROR] Main-thread work failed: {exception}");
}
}
}
public static void Shutdown()
{
IsAvailable = false;
try
{
_shutdownRequestHandler?.Invoke();
}
catch (Exception exception)
{
Console.Error.WriteLine($"[LOADER][WARN] Main-thread shutdown handler failed: {exception.Message}");
}
_work.CompleteAdding();
}
}