using System; using System.Collections.Generic; using System.Threading; namespace Crestron.SimplSharp { /// /// Mock implementation of Crestron CrestronQueue for testing purposes /// Provides the same public API surface as the real CrestronQueue /// /// Type of items in the queue public class CrestronQueue : IDisposable { #region Private Fields private readonly Queue _queue = new Queue(); private readonly object _lockObject = new object(); private readonly ManualResetEventSlim _dataAvailableEvent = new ManualResetEventSlim(false); private bool _disposed = false; #endregion #region Properties /// Gets the number of items in the queue public int Count { get { lock (_lockObject) { return _queue.Count; } } } /// Gets whether the queue is empty public bool IsEmpty { get { lock (_lockObject) { return _queue.Count == 0; } } } #endregion #region Constructor /// Initializes a new instance of the CrestronQueue class public CrestronQueue() { // Mock implementation } /// Initializes a new instance of the CrestronQueue class with specified capacity /// The initial capacity of the queue public CrestronQueue(int capacity) { // Mock implementation - capacity is ignored in this mock } #endregion #region Public Methods /// Adds an item to the end of the queue /// Item to add public void Enqueue(T item) { if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue)); lock (_lockObject) { _queue.Enqueue(item); _dataAvailableEvent.Set(); } } /// Removes and returns the item at the beginning of the queue /// The item that was removed from the queue /// Thrown when the queue is empty public T Dequeue() { if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue)); lock (_lockObject) { if (_queue.Count == 0) throw new InvalidOperationException("Queue is empty"); var item = _queue.Dequeue(); if (_queue.Count == 0) _dataAvailableEvent.Reset(); return item; } } /// Tries to remove and return the item at the beginning of the queue /// When successful, contains the dequeued item /// True if an item was successfully dequeued public bool TryDequeue(out T item) { if (_disposed) { item = default(T)!; return false; } lock (_lockObject) { if (_queue.Count == 0) { item = default(T)!; return false; } item = _queue.Dequeue(); if (_queue.Count == 0) _dataAvailableEvent.Reset(); return true; } } /// Returns the item at the beginning of the queue without removing it /// The item at the beginning of the queue /// Thrown when the queue is empty public T Peek() { if (_disposed) throw new ObjectDisposedException(nameof(CrestronQueue)); lock (_lockObject) { if (_queue.Count == 0) throw new InvalidOperationException("Queue is empty"); return _queue.Peek(); } } /// Tries to return the item at the beginning of the queue without removing it /// When successful, contains the item at the beginning of the queue /// True if an item was found public bool TryPeek(out T item) { if (_disposed) { item = default(T)!; return false; } lock (_lockObject) { if (_queue.Count == 0) { item = default(T)!; return false; } item = _queue.Peek(); return true; } } /// Removes all items from the queue public void Clear() { if (_disposed) return; lock (_lockObject) { _queue.Clear(); _dataAvailableEvent.Reset(); } } /// Waits for data to become available in the queue /// Timeout in milliseconds /// True if data became available within the timeout public bool WaitForData(int timeout) { if (_disposed) return false; return _dataAvailableEvent.Wait(timeout); } /// Waits for data to become available in the queue /// True when data becomes available public bool WaitForData() { if (_disposed) return false; _dataAvailableEvent.Wait(); return true; } /// Copies the queue elements to an array /// Array containing the queue elements public T[] ToArray() { if (_disposed) return new T[0]; lock (_lockObject) { return _queue.ToArray(); } } #endregion #region IDisposable Implementation /// Disposes the queue and releases resources public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// Protected dispose method /// True if disposing managed resources protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { _dataAvailableEvent?.Dispose(); Clear(); } _disposed = true; } } #endregion } }