aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation/TranslatorQueue.cs
diff options
context:
space:
mode:
authorFICTURE7 <FICTURE7@gmail.com>2022-09-09 03:14:08 +0400
committerGitHub <noreply@github.com>2022-09-08 20:14:08 -0300
commitee1825219b8ccca13df7198d4e9ffb966e44c883 (patch)
tree5d44ffc535393b574ab45c3e206264af948f3f6c /ARMeilleure/Translation/TranslatorQueue.cs
parent7baa08dcb4b38fe36bb19bf84b3fcd386d143463 (diff)
Clean up rejit queue (#2751)1.1.253
Diffstat (limited to 'ARMeilleure/Translation/TranslatorQueue.cs')
-rw-r--r--ARMeilleure/Translation/TranslatorQueue.cs121
1 files changed, 121 insertions, 0 deletions
diff --git a/ARMeilleure/Translation/TranslatorQueue.cs b/ARMeilleure/Translation/TranslatorQueue.cs
new file mode 100644
index 00000000..fc0aa64f
--- /dev/null
+++ b/ARMeilleure/Translation/TranslatorQueue.cs
@@ -0,0 +1,121 @@
+using ARMeilleure.Diagnostics;
+using ARMeilleure.State;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace ARMeilleure.Translation
+{
+ /// <summary>
+ /// Represents a queue of <see cref="RejitRequest"/>.
+ /// </summary>
+ /// <remarks>
+ /// This does not necessarily behave like a queue, i.e: a FIFO collection.
+ /// </remarks>
+ sealed class TranslatorQueue : IDisposable
+ {
+ private bool _disposed;
+ private readonly Stack<RejitRequest> _requests;
+ private readonly HashSet<ulong> _requestAddresses;
+
+ /// <summary>
+ /// Gets the object used to synchronize access to the <see cref="TranslatorQueue"/>.
+ /// </summary>
+ public object Sync { get; }
+
+ /// <summary>
+ /// Gets the number of requests in the <see cref="TranslatorQueue"/>.
+ /// </summary>
+ public int Count => _requests.Count;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TranslatorQueue"/> class.
+ /// </summary>
+ public TranslatorQueue()
+ {
+ Sync = new object();
+
+ _requests = new Stack<RejitRequest>();
+ _requestAddresses = new HashSet<ulong>();
+ }
+
+ /// <summary>
+ /// Enqueues a request with the specified <paramref name="address"/> and <paramref name="mode"/>.
+ /// </summary>
+ /// <param name="address">Address of request</param>
+ /// <param name="mode"><see cref="ExecutionMode"/> of request</param>
+ public void Enqueue(ulong address, ExecutionMode mode)
+ {
+ lock (Sync)
+ {
+ if (_requestAddresses.Add(address))
+ {
+ _requests.Push(new RejitRequest(address, mode));
+
+ TranslatorEventSource.Log.RejitQueueAdd(1);
+
+ Monitor.Pulse(Sync);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Tries to dequeue a <see cref="RejitRequest"/>. This will block the thread until a <see cref="RejitRequest"/>
+ /// is enqueued or the <see cref="TranslatorQueue"/> is disposed.
+ /// </summary>
+ /// <param name="result"><see cref="RejitRequest"/> dequeued</param>
+ /// <returns><see langword="true"/> on success; otherwise <see langword="false"/></returns>
+ public bool TryDequeue(out RejitRequest result)
+ {
+ while (!_disposed)
+ {
+ lock (Sync)
+ {
+ if (_requests.TryPop(out result))
+ {
+ _requestAddresses.Remove(result.Address);
+
+ TranslatorEventSource.Log.RejitQueueAdd(-1);
+
+ return true;
+ }
+
+ Monitor.Wait(Sync);
+ }
+ }
+
+ result = default;
+
+ return false;
+ }
+
+ /// <summary>
+ /// Clears the <see cref="TranslatorQueue"/>.
+ /// </summary>
+ public void Clear()
+ {
+ lock (Sync)
+ {
+ TranslatorEventSource.Log.RejitQueueAdd(-_requests.Count);
+
+ _requests.Clear();
+ _requestAddresses.Clear();
+
+ Monitor.PulseAll(Sync);
+ }
+ }
+
+ /// <summary>
+ /// Releases all resources used by the <see cref="TranslatorQueue"/> instance.
+ /// </summary>
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ _disposed = true;
+
+ Clear();
+ }
+ }
+ }
+}