using ARMeilleure.Diagnostics;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Threading;
namespace ARMeilleure.Translation
{
///
/// Represents a queue of .
///
///
/// This does not necessarily behave like a queue, i.e: a FIFO collection.
///
sealed class TranslatorQueue : IDisposable
{
private bool _disposed;
private readonly Stack _requests;
private readonly HashSet _requestAddresses;
///
/// Gets the object used to synchronize access to the .
///
public object Sync { get; }
///
/// Gets the number of requests in the .
///
public int Count => _requests.Count;
///
/// Initializes a new instance of the class.
///
public TranslatorQueue()
{
Sync = new object();
_requests = new Stack();
_requestAddresses = new HashSet();
}
///
/// Enqueues a request with the specified and .
///
/// Address of request
/// of request
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);
}
}
}
///
/// Tries to dequeue a . This will block the thread until a
/// is enqueued or the is disposed.
///
/// dequeued
/// on success; otherwise
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;
}
if (!_disposed)
{
Monitor.Wait(Sync);
}
}
}
result = default;
return false;
}
///
/// Clears the .
///
public void Clear()
{
lock (Sync)
{
TranslatorEventSource.Log.RejitQueueAdd(-_requests.Count);
_requests.Clear();
_requestAddresses.Clear();
Monitor.PulseAll(Sync);
}
}
///
/// Releases all resources used by the instance.
///
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Clear();
}
}
}
}