Files
DP44/Common/DTS.Common/Utils/SecureQueue.cs
2026-04-17 14:55:32 -04:00

167 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.Utils
{
public class SecureQueue<T> : IDisposable where T : new()
{
public enum NullPolicy
{
DenyNull, // throw an exception if try to Enqueue null or zero length
SkipNull, // don't complain but don't enqueue null or zero length
AllowNull // let null's in too
}
protected Queue<T[]> ByteQueue;
protected object ByteQueueLock;
protected ManualResetEvent ByteQueueEvent;
protected NullPolicy _NullPolicy;
protected string Name;
protected Stopwatch StopWatch;
public SecureQueue(NullPolicy policy, string name)
{
StopWatch = new Stopwatch();
StopWatch.Start();
ByteQueue = new Queue<T[]>();
ByteQueueLock = new object();
ByteQueueEvent = new ManualResetEvent(false);
_NullPolicy = policy;
Name = name;
}
public void ResetEvent()
{
//latestReset = GetCaller();
ByteQueueEvent.Reset();
}
public void Enqueue(T[] newData)
{
try
{
lock (ByteQueueLock)
{
if (newData == null || newData.Length == 0)
{
switch (_NullPolicy)
{
case NullPolicy.DenyNull:
throw new ArgumentException("SecureQueue_Enqueue_Err1");
case NullPolicy.SkipNull:
return;
}
}
ByteQueue.Enqueue((T[])newData?.Clone());
if (Enums.DASFactory.DFConstantsAndEnums.ExtraCommunicationLogging)
{
APILogger.Log("Enqueing data", newData);
}
ByteQueueEvent.Set();
}
}
catch (Exception ex)
{
APILogger.LogString("SecureQueue.Enqueue: The queue(" + Name + ") threw an exception. " + ex.Message + " " + ex.StackTrace);
throw;
}
}
/// <summary>
/// Wait for TimeoutMillisec milliseconds for data to arrive in the buffer. Returns false if it times out.
/// </summary>
/// <param name="timeoutMillisec"></param>
/// <returns>true if data has arrived, false if it times out</returns>
public bool WaitForData(int timeoutMillisec)
{
try
{
var result = ByteQueueEvent.WaitOne(timeoutMillisec, false);
return result;
}
catch (Exception ex)
{
APILogger.LogString("SecureQueue.WaitForData: The queue(" + Name + ") threw an exception. " + ex.Message + " " + ex.StackTrace);
}
return false;
}
public WaitHandle QueueWaitHandle => ByteQueueEvent;
public T[] Dequeue(bool resetEvent)
{
try
{
lock (ByteQueueLock)
{
ByteQueueEvent = new ManualResetEvent(false);
if (ByteQueue.Count == 0)
{
return new T[0];
}
if (ByteQueue.Count == 1)
{
var ret = ByteQueue.Dequeue();
return ret;
}
// count how much data we have
var totalBytes = ByteQueue.Sum(arr => arr.Length);
if (totalBytes == 0)
{
APILogger.LogString("SecureQueue.Dequeue: The queue(" + Name + ") has 0 bytes!");
}
// allocate that much
var result = new T[totalBytes];
var index = 0;
// now make one large array
while (ByteQueue.Any())
{
var element = ByteQueue.Dequeue();
Array.Copy(element, 0, result, index, element.Length);
index += element.Length;
}
return result;
}
}
catch (Exception ex)
{
APILogger.LogString("SecureQueue.Dequeue: The queue(" + Name + ") threw an exception. " + ex.Message + " " + ex.StackTrace);
}
return new T[0];
}
public void Flush()
{
try
{
lock (ByteQueueLock)
{
//latestFlush = GetCaller();
ByteQueueEvent = new ManualResetEvent(false);
ByteQueue.Clear();
}
}
catch (Exception ex)
{
APILogger.LogString("SecureQueue.Flush: The queue(" + Name + ") threw an exception. " + ex.Message + " " + ex.StackTrace);
}
}
public bool IsEmpty()
{
return ByteQueue.Count == 0;
}
public void Dispose()
{
}
}
}