diff --git a/.vscode/settings.json b/.vscode/settings.json index 17110cd..5105813 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "cSpell.words": [ "Cloudtoid", "Diagnoser", + "finalizer", "Interprocess", "Kaby", "Onnx", diff --git a/src/Interprocess/Queue/Subscriber.cs b/src/Interprocess/Queue/Subscriber.cs index 9a838bb..2947969 100644 --- a/src/Interprocess/Queue/Subscriber.cs +++ b/src/Interprocess/Queue/Subscriber.cs @@ -127,7 +127,7 @@ private unsafe bool TryDequeueImpl( var readOffset = Header->ReadOffset; var messageHeader = (MessageHeader*)Buffer.GetPointer(readOffset); - // was this message fully written by the publisher? if not, wait for the publisher to finish writting it + // was this message fully written by the publisher? if not, wait for the publisher to finish writing it while (Interlocked.CompareExchange( ref messageHeader->State, MessageHeader.LockedToBeConsumedState, diff --git a/src/Interprocess/Semaphore/MacOS/Interop.cs b/src/Interprocess/Semaphore/MacOS/Interop.cs index a70d84c..5bb3ccd 100644 --- a/src/Interprocess/Semaphore/MacOS/Interop.cs +++ b/src/Interprocess/Semaphore/MacOS/Interop.cs @@ -96,10 +96,10 @@ internal static bool Wait(IntPtr handle, int millisecondsTimeout) } else { - var start = DateTime.Now; + var stopwatch = ValueStopwatch.StartNew(); while (!TryWait(handle)) { - if ((DateTime.Now - start).Milliseconds > millisecondsTimeout) + if (stopwatch.GetElapsedTime().TotalMilliseconds > millisecondsTimeout) return false; Thread.Yield(); diff --git a/src/Interprocess/ValueStopwatch.cs b/src/Interprocess/ValueStopwatch.cs new file mode 100644 index 0000000..5399e58 --- /dev/null +++ b/src/Interprocess/ValueStopwatch.cs @@ -0,0 +1,25 @@ +using System.Diagnostics; + +namespace Cloudtoid.Interprocess; + +// Inspired by https://github.com/dotnet/aspnetcore/blob/main/src/Shared/ValueStopwatch/ValueStopwatch.cs +internal readonly struct ValueStopwatch +{ + private readonly long start; + private ValueStopwatch(long start) => this.start = start; + public readonly bool IsActive => start != 0; + public static ValueStopwatch StartNew() => new(Stopwatch.GetTimestamp()); + + public readonly TimeSpan GetElapsedTime() + { + // Start timestamp can't be zero in an initialized ValueStopwatch. It would have to be literally the first thing executed when the machine boots to be 0. + // So it being 0 is a clear indication of default(ValueStopwatch) + if (!IsActive) + { + throw new InvalidOperationException( + "An uninitialized, or 'default', ValueStopwatch cannot be used to get elapsed time."); + } + + return Stopwatch.GetElapsedTime(start); + } +} \ No newline at end of file