mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
79 lines
2.3 KiB
C#
79 lines
2.3 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Channels;
|
|
using System.Threading.Tasks;
|
|
using Robust.Shared.Exceptions;
|
|
|
|
namespace Robust.Shared.Asynchronous
|
|
{
|
|
internal sealed class RobustSynchronizationContext : SynchronizationContext
|
|
{
|
|
// Used only on release.
|
|
// ReSharper disable once NotAccessedField.Local
|
|
private readonly IRuntimeLog _runtimeLog;
|
|
|
|
public RobustSynchronizationContext(IRuntimeLog runtimeLog)
|
|
{
|
|
_runtimeLog = runtimeLog;
|
|
|
|
var channel = Channel.CreateUnbounded<Mail>(new UnboundedChannelOptions
|
|
{
|
|
SingleReader = true,
|
|
SingleWriter = false,
|
|
// For unblocking continuations.
|
|
AllowSynchronousContinuations = true
|
|
});
|
|
|
|
_channelReader = channel.Reader;
|
|
_channelWriter = channel.Writer;
|
|
}
|
|
|
|
private readonly ChannelReader<Mail> _channelReader;
|
|
private readonly ChannelWriter<Mail> _channelWriter;
|
|
|
|
public override void Send(SendOrPostCallback d, object? state)
|
|
{
|
|
if (Current != this)
|
|
{
|
|
// Being invoked from another thread?
|
|
// If this not implemented exception starts being a problem I'll fix it but right now I'd rather err on the side of caution,
|
|
// so that if cross thread usage is required I have a test case, instead of a data race.
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
d(state);
|
|
}
|
|
|
|
public override void Post(SendOrPostCallback d, object? state)
|
|
{
|
|
_channelWriter.TryWrite(new Mail(d, state));
|
|
}
|
|
|
|
public void ProcessPendingTasks()
|
|
{
|
|
while (_channelReader.TryRead(out var task))
|
|
{
|
|
#if EXCEPTION_TOLERANCE
|
|
try
|
|
#endif
|
|
{
|
|
task.Callback(task.State);
|
|
}
|
|
#if EXCEPTION_TOLERANCE
|
|
catch (Exception e)
|
|
{
|
|
_runtimeLog.LogException(e, "Async Queued Callback");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
public ValueTask<bool> WaitOnPendingTasks()
|
|
{
|
|
return _channelReader.WaitToReadAsync();
|
|
}
|
|
|
|
private record struct Mail(SendOrPostCallback Callback, object? State);
|
|
}
|
|
}
|