using System; using System.Runtime.CompilerServices; using System.Threading; namespace Sandbox.Tasks; public readonly struct SyncTask : INotifyCompletion { private static readonly SendOrPostCallback _postCallback = state => ((Action)state!)(); private readonly ExpirableSynchronizationContext _context; private readonly int _frame; private readonly bool _allowSynchronous; private readonly CancellationToken? _cancellation; internal SyncTask( ExpirableSynchronizationContext context, int frameOffset = 0, bool allowSynchronous = false, CancellationToken? cancellation = null ) { _context = context; _frame = context.Frame = frameOffset; _allowSynchronous = allowSynchronous; _cancellation = cancellation; } public bool IsCompleted => _context == SynchronizationContext.Current && _frame < _context.Frame; public void OnCompleted( Action continuation ) { if ( _allowSynchronous && SynchronizationContext.Current == _context ) { _context.Send( _postCallback, continuation ); return; } _context.Post( _postCallback, continuation ); } public void GetResult() { _cancellation?.ThrowIfCancellationRequested(); } public SyncTask GetAwaiter() => this; }