Added handling for OperationCanceledException

This commit is contained in:
Thorsten Sommer 2020-09-26 13:33:04 +02:00
parent 2b0e92a91d
commit 29a913843a

View File

@ -20,7 +20,7 @@ namespace FastRng.Double
private const int CAPACITY_RANDOM_NUMBERS_4_SOURCE = 16_000_000; private const int CAPACITY_RANDOM_NUMBERS_4_SOURCE = 16_000_000;
#endif #endif
private readonly CancellationTokenSource producerToken = new CancellationTokenSource(); private readonly CancellationTokenSource producerTokenSource = new CancellationTokenSource();
private readonly object syncUintGenerators = new object(); private readonly object syncUintGenerators = new object();
private readonly object syncUniformDistributedDoubleGenerators = new object(); private readonly object syncUniformDistributedDoubleGenerators = new object();
private readonly Thread[] producerRandomUint = new Thread[2]; private readonly Thread[] producerRandomUint = new Thread[2];
@ -74,13 +74,13 @@ namespace FastRng.Double
private void StartProducerThreads() private void StartProducerThreads()
{ {
this.producerRandomUint[0] = new Thread(() => this.RandomProducerUint(this.channelRandomUint.Writer, this.producerToken.Token)) {IsBackground = true}; this.producerRandomUint[0] = new Thread(() => this.RandomProducerUint(this.channelRandomUint.Writer, this.producerTokenSource.Token)) {IsBackground = true};
this.producerRandomUint[1] = new Thread(() => this.RandomProducerUint(this.channelRandomUint.Writer, this.producerToken.Token)) {IsBackground = true}; this.producerRandomUint[1] = new Thread(() => this.RandomProducerUint(this.channelRandomUint.Writer, this.producerTokenSource.Token)) {IsBackground = true};
this.producerRandomUint[0].Start(); this.producerRandomUint[0].Start();
this.producerRandomUint[1].Start(); this.producerRandomUint[1].Start();
this.producerRandomUniformDistributedDouble[0] = new Thread(() => this.RandomProducerUniformDistributedDouble(this.channelRandomUint.Reader, channelRandomUniformDistributedDouble.Writer, this.producerToken.Token)) {IsBackground = true}; this.producerRandomUniformDistributedDouble[0] = new Thread(() => this.RandomProducerUniformDistributedDouble(this.channelRandomUint.Reader, channelRandomUniformDistributedDouble.Writer, this.producerTokenSource.Token)) {IsBackground = true};
this.producerRandomUniformDistributedDouble[1] = new Thread(() => this.RandomProducerUniformDistributedDouble(this.channelRandomUint.Reader, channelRandomUniformDistributedDouble.Writer, this.producerToken.Token)) {IsBackground = true}; this.producerRandomUniformDistributedDouble[1] = new Thread(() => this.RandomProducerUniformDistributedDouble(this.channelRandomUint.Reader, channelRandomUniformDistributedDouble.Writer, this.producerTokenSource.Token)) {IsBackground = true};
this.producerRandomUniformDistributedDouble[0].Start(); this.producerRandomUniformDistributedDouble[0].Start();
this.producerRandomUniformDistributedDouble[1].Start(); this.producerRandomUniformDistributedDouble[1].Start();
} }
@ -91,6 +91,8 @@ namespace FastRng.Double
[ExcludeFromCodeCoverage] [ExcludeFromCodeCoverage]
private async void RandomProducerUint(ChannelWriter<uint> channelWriter, CancellationToken cancellationToken) private async void RandomProducerUint(ChannelWriter<uint> channelWriter, CancellationToken cancellationToken)
{
try
{ {
var buffer = new uint[CAPACITY_RANDOM_NUMBERS_4_SOURCE]; var buffer = new uint[CAPACITY_RANDOM_NUMBERS_4_SOURCE];
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
@ -109,9 +111,15 @@ namespace FastRng.Double
await channelWriter.WriteAsync(buffer[n], cancellationToken); await channelWriter.WriteAsync(buffer[n], cancellationToken);
} }
} }
catch (OperationCanceledException)
{
}
}
[ExcludeFromCodeCoverage] [ExcludeFromCodeCoverage]
private async void RandomProducerUniformDistributedDouble(ChannelReader<uint> channelReaderUint, ChannelWriter<double> channelWriter, CancellationToken cancellationToken) private async void RandomProducerUniformDistributedDouble(ChannelReader<uint> channelReaderUint, ChannelWriter<double> channelWriter, CancellationToken cancellationToken)
{
try
{ {
var buffer = new double[CAPACITY_RANDOM_NUMBERS_4_SOURCE]; var buffer = new double[CAPACITY_RANDOM_NUMBERS_4_SOURCE];
var randomUint = new uint[CAPACITY_RANDOM_NUMBERS_4_SOURCE]; var randomUint = new uint[CAPACITY_RANDOM_NUMBERS_4_SOURCE];
@ -128,12 +136,26 @@ namespace FastRng.Double
await channelWriter.WriteAsync(buffer[n], cancellationToken); await channelWriter.WriteAsync(buffer[n], cancellationToken);
} }
} }
catch (OperationCanceledException)
{
}
}
#endregion #endregion
#region Implementing interface #region Implementing interface
public async ValueTask<double> GetUniform(CancellationToken cancel = default) => await this.channelRandomUniformDistributedDouble.Reader.ReadAsync(cancel); public async ValueTask<double> GetUniform(CancellationToken cancel = default)
{
try
{
return await this.channelRandomUniformDistributedDouble.Reader.ReadAsync(cancel);
}
catch (OperationCanceledException)
{
return double.NaN;
}
}
public async ValueTask<uint> NextNumber(uint rangeStart, uint rangeEnd, IDistribution distribution, CancellationToken cancel = default) public async ValueTask<uint> NextNumber(uint rangeStart, uint rangeEnd, IDistribution distribution, CancellationToken cancel = default)
{ {
@ -147,9 +169,16 @@ namespace FastRng.Double
var range = rangeEnd - rangeStart; var range = rangeEnd - rangeStart;
distribution.Random = this; distribution.Random = this;
try
{
var distributedValue = await distribution.GetDistributedValue(cancel); var distributedValue = await distribution.GetDistributedValue(cancel);
return (uint) ((distributedValue * range) + rangeStart); return (uint) ((distributedValue * range) + rangeStart);
} }
catch (OperationCanceledException)
{
return 0;
}
}
public async ValueTask<ulong> NextNumber(ulong rangeStart, ulong rangeEnd, IDistribution distribution, CancellationToken cancel = default(CancellationToken)) public async ValueTask<ulong> NextNumber(ulong rangeStart, ulong rangeEnd, IDistribution distribution, CancellationToken cancel = default(CancellationToken))
{ {
@ -163,9 +192,16 @@ namespace FastRng.Double
var range = rangeEnd - rangeStart; var range = rangeEnd - rangeStart;
distribution.Random = this; distribution.Random = this;
try
{
var distributedValue = await distribution.GetDistributedValue(cancel); var distributedValue = await distribution.GetDistributedValue(cancel);
return (ulong) ((distributedValue * range) + rangeStart); return (ulong) ((distributedValue * range) + rangeStart);
} }
catch (OperationCanceledException)
{
return 0;
}
}
public async ValueTask<double> NextNumber(double rangeStart, double rangeEnd, IDistribution distribution, CancellationToken cancel = default(CancellationToken)) public async ValueTask<double> NextNumber(double rangeStart, double rangeEnd, IDistribution distribution, CancellationToken cancel = default(CancellationToken))
{ {
@ -179,13 +215,20 @@ namespace FastRng.Double
var range = rangeEnd - rangeStart; var range = rangeEnd - rangeStart;
distribution.Random = this; distribution.Random = this;
try
{
var distributedValue = await distribution.GetDistributedValue(cancel); var distributedValue = await distribution.GetDistributedValue(cancel);
return (distributedValue * range) + rangeStart; return (distributedValue * range) + rangeStart;
} }
catch (OperationCanceledException)
{
return double.NaN;
}
}
public async ValueTask<double> NextNumber(IDistribution distribution, CancellationToken cancel = default) => await this.NextNumber(0.0, 1.0, distribution, cancel); public async ValueTask<double> NextNumber(IDistribution distribution, CancellationToken cancel = default) => await this.NextNumber(0.0, 1.0, distribution, cancel);
public void StopProducer() => this.producerToken.Cancel(); public void StopProducer() => this.producerTokenSource.Cancel();
#endregion #endregion
} }