mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-06 21:38:32 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
114 lines
2.1 KiB
C#
114 lines
2.1 KiB
C#
using System.Threading;
|
|
using System.Threading.Channels;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// Utility functions that revolve around the main thread
|
|
/// </summary>
|
|
public static class MainThread
|
|
{
|
|
static Channel<IDisposable> Disposables = Channel.CreateUnbounded<IDisposable>();
|
|
static Channel<Action> Actions = Channel.CreateUnbounded<Action>();
|
|
|
|
/// <summary>
|
|
/// Wait to execute on the main thread
|
|
/// </summary>
|
|
public static SyncTask Wait()
|
|
{
|
|
return new SyncTask( SyncContext.MainThread, allowSynchronous: true );
|
|
}
|
|
|
|
|
|
internal static void QueueDispose( IDisposable disposable )
|
|
{
|
|
if ( disposable is null )
|
|
return;
|
|
|
|
if ( ThreadSafe.IsMainThread )
|
|
{
|
|
disposable.Dispose();
|
|
return;
|
|
}
|
|
|
|
Disposables.Writer.TryWrite( disposable );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Run a function on the main thread and wait for the result.
|
|
/// </summary>
|
|
internal static T Run<T>( int millisecondsTimeout, Func<T> func )
|
|
{
|
|
if ( ThreadSafe.IsMainThread )
|
|
return func();
|
|
|
|
T r = default;
|
|
ManualResetEvent reset = new ManualResetEvent( false );
|
|
|
|
Queue( () =>
|
|
{
|
|
try
|
|
{
|
|
r = func();
|
|
}
|
|
finally
|
|
{
|
|
reset.Set();
|
|
}
|
|
} );
|
|
|
|
if ( !reset.WaitOne( millisecondsTimeout ) )
|
|
{
|
|
return default;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
internal static void RunQueues()
|
|
{
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
while ( Disposables.Reader.TryRead( out var disposable ) )
|
|
{
|
|
disposable.Dispose();
|
|
}
|
|
|
|
RunMainThreadQueues();
|
|
}
|
|
|
|
/// <summary>
|
|
/// When running in another thread you can queue a method to run in the main thread.
|
|
/// If you are on the main thread we will execute the method immediately and return.
|
|
/// </summary>
|
|
public static void Queue( Action method )
|
|
{
|
|
if ( ThreadSafe.IsMainThread )
|
|
{
|
|
method();
|
|
return;
|
|
}
|
|
|
|
Actions.Writer.TryWrite( method );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Run queued actions on the main thread
|
|
/// </summary>
|
|
internal static void RunMainThreadQueues()
|
|
{
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
while ( Actions.Reader.TryRead( out var action ) )
|
|
{
|
|
try
|
|
{
|
|
action();
|
|
}
|
|
catch ( System.Exception e )
|
|
{
|
|
Log.Warning( e, e.Message );
|
|
}
|
|
}
|
|
}
|
|
}
|