public volatile int lastSeqNumOut; // sequence number of the last message to have been taken from the queue (queue is likely empty if they are both the same) #endregion Fields #region Constructors public QueuedMesgSeqNumRange(ref QueuedMesgSeqNumRange rhs) { // grab the out sequence number before the in so that we are most inclusive when making a copy of another QueuedMesgSeqNumRange value. // order matters here since these are volatile (values may be written in the background by other threads while reading..) lastSeqNumOut = rhs.lastSeqNumOut; lastSeqNumIn = rhs.lastSeqNumIn; }
public bool IsMessageStillInQueue(int testSeqNum) { lock (queueMutex) { QueuedMesgSeqNumRange queuedMesgSeqNumRangeSnapshot = new QueuedMesgSeqNumRange(ref queuedMesgSeqNumRange); return(queuedMesgSeqNumRangeSnapshot.IsMesgSeqNumInRange(testSeqNum)); } }
public bool IsMessageStillInQueue(int testSeqNum) { lock (queueMutex) { QueuedMesgSeqNumRange queuedMesgSeqNumRangeSnapshot = new QueuedMesgSeqNumRange(ref queuedMesgSeqNumRange); return queuedMesgSeqNumRangeSnapshot.IsMesgSeqNumInRange(testSeqNum); } }
const double minDeliveryThreadSpinWaitPeriod = 0.050; // 20 Hz /// <summary> /// This gives the method that is called by the internal service thread to pull messages from the back of the message queue and deliver them to the /// target LMH instances. /// </summary> protected void MainThreadFcn() { if (targetLMHArray == null || !mesgQueue.IsEnabled || threadWakeupEvent == null) { mesgQueue.DisableQueue(); foreach (var lmh in targetLMHArray ?? emptyLMHArray) { lmh.Shutdown(); } Utils.Asserts.TakeBreakpointAfterFault("QLMH thread Startup test failed"); return; } foreach (var lmh in targetLMHArray) { lmh.StartIfNeeded(); } while (mesgQueue.IsEnabled) { threadWakeupEvent.Reset(); bool didAnything = false; // process messages from a non-empty queue (or full) if (mesgQueue.QueueCount != 0 || mesgQueue.IsQueueFull()) { didAnything = true; ServiceQueueDelivery(maxMessagesToDequePerIteration); } // detect seqNum based flush request and ask underlying lmh to flush after // given seqNum is no longer in the mesgQueue int flushReqSeqNumSnapshot = flushAfterSeqNum; QueuedMesgSeqNumRange mesgQueueSeqNumRangeSnapshot = mesgQueueSeqNumRange; if (NullMessageSeqNum != flushReqSeqNumSnapshot && !mesgQueueSeqNumRangeSnapshot.IsMesgSeqNumInRange(flushReqSeqNumSnapshot)) { flushRequested = true; flushAfterSeqNum = NullMessageSeqNum; } if (flushRequested) // when queue is empty then process flush request { didAnything = true; flushRequested = false; foreach (var lmh in targetLMHArray) { lmh.Flush(); } } if (!didAnything) { threadWakeupEvent.WaitSec(minDeliveryThreadSpinWaitPeriod); } } // service the queue until it is empty while (mesgQueue.QueueCount != 0 || mesgQueue.IsQueueFull()) { ServiceQueueDelivery(maxMessagesToDequePerIteration); } uint totalDroppedMesgs = mesgQueue.TotalDroppedMesgCount; if (totalDroppedMesgs != 0) { LogShutdownDroppedMessagesMesg(totalDroppedMesgs); } foreach (var lmh in targetLMHArray) { lmh.Shutdown(); } }
/// <summary>Query method that may be used to tell if message delivery for a given message is still in progress on this handler.</summary> public override bool IsMessageDeliveryInProgress(int testMesgSeqNum) { QueuedMesgSeqNumRange mesgQueueSeqNumRangeSnapshot = mesgQueueSeqNumRange; return(mesgQueueSeqNumRangeSnapshot.IsMesgSeqNumInRange(testMesgSeqNum)); }
/// <summary> /// Copy constructor. /// <para/>grab the out sequence number before the in so that we are most inclusive when making a copy of another QueuedMesgSeqNumRange value. /// order matters here since these are volatile (values may be written in the background by other threads while reading..) /// </summary> public QueuedMesgSeqNumRange(ref QueuedMesgSeqNumRange rhs) { lastSeqNumOut = rhs.lastSeqNumOut; lastSeqNumIn = rhs.lastSeqNumIn; }