From 816ff4b4d8981f9c136f21787c2eb1a7c762b348 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 14:57:56 +0000 Subject: [PATCH 1/8] Initial plan From 4fd1812c82263064f4491123cc64046c03c530b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:08:36 +0000 Subject: [PATCH 2/8] Add stress test for message queue clearing before nextQueued() Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- jcstress-results-2026-02-15-15-07-23.bin.gz | Bin 0 -> 10 bytes .../quickfix/MessageQueueClearStressTest.java | 201 ++++++++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 jcstress-results-2026-02-15-15-07-23.bin.gz create mode 100644 quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java diff --git a/jcstress-results-2026-02-15-15-07-23.bin.gz b/jcstress-results-2026-02-15-15-07-23.bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..5105e8bffba55252e59dd361d3906d03eb845364 GIT binary patch literal 10 Ncmb2|=3oGW{{RPK0kQx9 literal 0 HcmV?d00001 diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java new file mode 100644 index 000000000..ec87fdf08 --- /dev/null +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -0,0 +1,201 @@ +package quickfix; + +import org.openjdk.jcstress.annotations.Actor; +import org.openjdk.jcstress.annotations.Arbiter; +import org.openjdk.jcstress.annotations.Expect; +import org.openjdk.jcstress.annotations.JCStressTest; +import org.openjdk.jcstress.annotations.Outcome; +import org.openjdk.jcstress.annotations.State; +import org.openjdk.jcstress.infra.results.III_Result; + +import quickfix.field.BeginString; +import quickfix.field.MsgSeqNum; +import quickfix.field.MsgType; +import quickfix.field.SenderCompID; +import quickfix.field.TargetCompID; + +/** + * Stress test that validates messages can be cleared from the queue before + * they will be picked up via call to nextQueued() in the Session class. + * + * This test is related to PR #1133 which tests SequenceReset with GapFill + * functionality that removes queued messages when the gap fill extends beyond them. + * + * The test simulates a race condition where: + * - One actor is trying to process queued messages (via nextQueued) + * - Another actor is trying to clear messages from the queue (via dequeueMessagesUpTo) + * - The test validates that either all messages are cleared before processing, + * or some are processed before clearing, but no message is both processed and cleared + */ +@SuppressWarnings("unused") +public class MessageQueueClearStressTest { + + /** + * Tests the race between dequeuing messages and clearing them. + * Acceptable outcomes: + * - 0 processed, 0 in queue: All messages were cleared before dequeue attempt + * - N processed, 0 in queue: Messages were processed then cleared + * Unacceptable outcomes: + * - Lost updates or inconsistent state between processing and clearing + */ + @State + @JCStressTest + @Outcome(id = "0, 0, 0", expect = Expect.ACCEPTABLE, desc = "All messages cleared before processing") + @Outcome(id = "1, 0, 0", expect = Expect.ACCEPTABLE, desc = "One message processed, rest cleared") + @Outcome(id = "2, 0, 0", expect = Expect.ACCEPTABLE, desc = "Two messages processed, rest cleared") + @Outcome(id = "3, 0, 0", expect = Expect.ACCEPTABLE, desc = "All messages processed before clear") + @Outcome(expect = Expect.FORBIDDEN, desc = "Inconsistent state detected") + public static class ClearBeforeNextQueuedTest { + + private final MessageQueueWrapper wrapper; + + public ClearBeforeNextQueuedTest() { + this.wrapper = new MessageQueueWrapper(); + } + + // Actor 1: Thread trying to process queued messages (simulates nextQueued) + @Actor + public void processQueuedMessages() { + wrapper.processNextQueued(); + } + + // Actor 2: Thread trying to clear messages from queue (simulates SequenceReset gap fill) + @Actor + public void clearQueuedMessages() { + wrapper.clearMessagesUpTo(10); + } + + @Arbiter + public void captureResult(III_Result result) { + result.r1 = wrapper.getProcessedCount(); + result.r2 = wrapper.getQueueSize(); + result.r3 = wrapper.getClearedCount(); + } + } + + /** + * Tests concurrent clearing with multiple sequence resets. + * This simulates a scenario where multiple SequenceReset messages might arrive + * while messages are being queued and processed. + */ + @State + @JCStressTest + @Outcome(id = "0, 0", expect = Expect.ACCEPTABLE, desc = "All messages cleared") + @Outcome(id = "1, 0", expect = Expect.ACCEPTABLE, desc = "One message processed") + @Outcome(id = "2, 0", expect = Expect.ACCEPTABLE, desc = "Two messages processed") + @Outcome(id = "3, 0", expect = Expect.ACCEPTABLE, desc = "Three messages processed") + @Outcome(id = "4, 0", expect = Expect.ACCEPTABLE, desc = "Four messages processed") + @Outcome(id = "5, 0", expect = Expect.ACCEPTABLE, desc = "All messages processed") + @Outcome(expect = Expect.FORBIDDEN, desc = "Messages remaining in queue") + public static class MultipleSequenceResetTest { + + private final MessageQueueWrapper wrapper; + + public MultipleSequenceResetTest() { + this.wrapper = new MessageQueueWrapper(); + } + + // Actor 1: Process queued messages + @Actor + public void processMessages() { + wrapper.processNextQueued(); + } + + // Actor 2: First SequenceReset clearing messages + @Actor + public void firstSequenceReset() { + wrapper.clearMessagesUpTo(5); + } + + // Actor 3: Second SequenceReset clearing more messages + @Actor + public void secondSequenceReset() { + wrapper.clearMessagesUpTo(10); + } + + @Arbiter + public void captureResult(org.openjdk.jcstress.infra.results.II_Result result) { + result.r1 = wrapper.getProcessedCount(); + result.r2 = wrapper.getQueueSize(); + } + } + + /** + * Wrapper class that simulates Session's message queue behavior. + * This includes enqueueing, dequeuing, and clearing messages. + */ + private static final class MessageQueueWrapper { + + private final InMemoryMessageQueue queue; + private int processedCount; + private int clearedCount; + + public MessageQueueWrapper() { + this.queue = new InMemoryMessageQueue(); + this.processedCount = 0; + this.clearedCount = 0; + + // Pre-populate queue with messages (simulating out-of-sequence messages) + // These messages have sequence numbers from 5 to 9 + for (int i = 5; i <= 9; i++) { + try { + Message msg = createMessage(i); + queue.enqueue(i, msg); + } catch (Exception e) { + throw new RuntimeException("Failed to create test message", e); + } + } + } + + /** + * Simulates the nextQueued() method behavior - attempts to process + * all queued messages in sequence order. + */ + public synchronized void processNextQueued() { + // Try to process messages starting from sequence 5 + for (int seqNum = 5; seqNum <= 9; seqNum++) { + Message msg = queue.dequeue(seqNum); + if (msg != null) { + processedCount++; + } + } + } + + /** + * Simulates SequenceReset gap fill behavior - clears all messages + * with sequence numbers less than the specified value. + */ + public synchronized void clearMessagesUpTo(int newSeqNum) { + // Clear messages up to the new sequence number + int sizeBefore = queue.getBackingMap().size(); + queue.dequeueMessagesUpTo(newSeqNum); + int sizeAfter = queue.getBackingMap().size(); + clearedCount = sizeBefore - sizeAfter; + } + + public int getProcessedCount() { + return processedCount; + } + + public int getQueueSize() { + return queue.getBackingMap().size(); + } + + public int getClearedCount() { + return clearedCount; + } + + /** + * Creates a simple FIX message for testing. + */ + private Message createMessage(int seqNum) throws Exception { + Message msg = new Message(); + msg.getHeader().setString(BeginString.FIELD, "FIX.4.4"); + msg.getHeader().setString(MsgType.FIELD, "D"); // NewOrderSingle + msg.getHeader().setString(SenderCompID.FIELD, "SENDER"); + msg.getHeader().setString(TargetCompID.FIELD, "TARGET"); + msg.getHeader().setInt(MsgSeqNum.FIELD, seqNum); + return msg; + } + } +} From d9fe9a9101f7678b96888e08c28c495999c47e34 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:08:57 +0000 Subject: [PATCH 3/8] Remove test result file and update .gitignore Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .gitignore | 3 +++ jcstress-results-2026-02-15-15-07-23.bin.gz | Bin 10 -> 0 bytes 2 files changed, 3 insertions(+) delete mode 100644 jcstress-results-2026-02-15-15-07-23.bin.gz diff --git a/.gitignore b/.gitignore index fb838987e..d892c9875 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ nb-configuration.xml *.bak # ignore vim swap files *.swp +# ignore jcstress test results +jcstress-results-*.bin.gz +results/ diff --git a/jcstress-results-2026-02-15-15-07-23.bin.gz b/jcstress-results-2026-02-15-15-07-23.bin.gz deleted file mode 100644 index 5105e8bffba55252e59dd361d3906d03eb845364..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10 Ncmb2|=3oGW{{RPK0kQx9 From 30e88b08368704f695d6bbe075215d9acf594c7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:11:59 +0000 Subject: [PATCH 4/8] Fix stress test outcomes and add comprehensive documentation Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../quickfix/MessageQueueClearStressTest.java | 54 +++++++++++-------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java index ec87fdf08..6c46e2e60 100644 --- a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -21,11 +21,27 @@ * This test is related to PR #1133 which tests SequenceReset with GapFill * functionality that removes queued messages when the gap fill extends beyond them. * - * The test simulates a race condition where: + * The test simulates race conditions where: * - One actor is trying to process queued messages (via nextQueued) - * - Another actor is trying to clear messages from the queue (via dequeueMessagesUpTo) - * - The test validates that either all messages are cleared before processing, - * or some are processed before clearing, but no message is both processed and cleared + * - Other actors are trying to clear messages from the queue (via dequeueMessagesUpTo) + * - The test validates that the queue operations are thread-safe and no messages + * are lost or left in an inconsistent state + * + * Key scenarios tested: + * 1. ClearBeforeNextQueuedTest: Tests the basic race between processing and clearing + * - Uses synchronized methods to ensure atomicity + * - Validates that either messages are cleared OR processed, never both + * - Confirms the queue is always empty after both operations complete + * + * 2. MultipleSequenceResetTest: Tests concurrent clearing with multiple resets + * - Simulates multiple SequenceReset messages arriving concurrently + * - Tests the interaction between processing and multiple clearing operations + * - Ensures consistent state even with multiple concurrent clear operations + * + * Expected outcomes: + * - All acceptable outcomes should have 0 messages remaining in the queue + * - The number of processed messages can vary from 0 to the total count + * - No inconsistent states (e.g., messages stuck in queue, double processing) */ @SuppressWarnings("unused") public class MessageQueueClearStressTest { @@ -34,17 +50,19 @@ public class MessageQueueClearStressTest { * Tests the race between dequeuing messages and clearing them. * Acceptable outcomes: * - 0 processed, 0 in queue: All messages were cleared before dequeue attempt - * - N processed, 0 in queue: Messages were processed then cleared - * Unacceptable outcomes: - * - Lost updates or inconsistent state between processing and clearing + * - N processed, 0 in queue: N messages were processed, rest cleared + * The key is that the queue should always be empty after both operations + * and the sum of processed + messages in queue should not exceed original count */ @State @JCStressTest - @Outcome(id = "0, 0, 0", expect = Expect.ACCEPTABLE, desc = "All messages cleared before processing") - @Outcome(id = "1, 0, 0", expect = Expect.ACCEPTABLE, desc = "One message processed, rest cleared") - @Outcome(id = "2, 0, 0", expect = Expect.ACCEPTABLE, desc = "Two messages processed, rest cleared") - @Outcome(id = "3, 0, 0", expect = Expect.ACCEPTABLE, desc = "All messages processed before clear") - @Outcome(expect = Expect.FORBIDDEN, desc = "Inconsistent state detected") + @Outcome(id = "0, 0", expect = Expect.ACCEPTABLE, desc = "All messages cleared before processing") + @Outcome(id = "1, 0", expect = Expect.ACCEPTABLE, desc = "One message processed, rest cleared") + @Outcome(id = "2, 0", expect = Expect.ACCEPTABLE, desc = "Two messages processed, rest cleared") + @Outcome(id = "3, 0", expect = Expect.ACCEPTABLE, desc = "Three messages processed, rest cleared") + @Outcome(id = "4, 0", expect = Expect.ACCEPTABLE, desc = "Four messages processed, rest cleared") + @Outcome(id = "5, 0", expect = Expect.ACCEPTABLE, desc = "All messages processed before clear") + @Outcome(expect = Expect.FORBIDDEN, desc = "Messages remaining in queue or inconsistent state") public static class ClearBeforeNextQueuedTest { private final MessageQueueWrapper wrapper; @@ -66,10 +84,9 @@ public void clearQueuedMessages() { } @Arbiter - public void captureResult(III_Result result) { + public void captureResult(org.openjdk.jcstress.infra.results.II_Result result) { result.r1 = wrapper.getProcessedCount(); result.r2 = wrapper.getQueueSize(); - result.r3 = wrapper.getClearedCount(); } } @@ -128,12 +145,10 @@ private static final class MessageQueueWrapper { private final InMemoryMessageQueue queue; private int processedCount; - private int clearedCount; public MessageQueueWrapper() { this.queue = new InMemoryMessageQueue(); this.processedCount = 0; - this.clearedCount = 0; // Pre-populate queue with messages (simulating out-of-sequence messages) // These messages have sequence numbers from 5 to 9 @@ -167,10 +182,7 @@ public synchronized void processNextQueued() { */ public synchronized void clearMessagesUpTo(int newSeqNum) { // Clear messages up to the new sequence number - int sizeBefore = queue.getBackingMap().size(); queue.dequeueMessagesUpTo(newSeqNum); - int sizeAfter = queue.getBackingMap().size(); - clearedCount = sizeBefore - sizeAfter; } public int getProcessedCount() { @@ -181,10 +193,6 @@ public int getQueueSize() { return queue.getBackingMap().size(); } - public int getClearedCount() { - return clearedCount; - } - /** * Creates a simple FIX message for testing. */ From 923f70ca4e63f64694bc979f4473db6670677a8a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:12:47 +0000 Subject: [PATCH 5/8] Remove unused import III_Result Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../src/main/java/quickfix/MessageQueueClearStressTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java index 6c46e2e60..472642e63 100644 --- a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -6,7 +6,6 @@ import org.openjdk.jcstress.annotations.JCStressTest; import org.openjdk.jcstress.annotations.Outcome; import org.openjdk.jcstress.annotations.State; -import org.openjdk.jcstress.infra.results.III_Result; import quickfix.field.BeginString; import quickfix.field.MsgSeqNum; From 324cdc30a3fa7eac8aec95533040cd7e3a622e7a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:18:18 +0000 Subject: [PATCH 6/8] Restore synchronization and use AtomicInteger for thread-safe counter Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../quickfix/MessageQueueClearStressTest.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java index 472642e63..aef51370e 100644 --- a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -1,5 +1,7 @@ package quickfix; +import java.util.concurrent.atomic.AtomicInteger; + import org.openjdk.jcstress.annotations.Actor; import org.openjdk.jcstress.annotations.Arbiter; import org.openjdk.jcstress.annotations.Expect; @@ -47,11 +49,18 @@ public class MessageQueueClearStressTest { /** * Tests the race between dequeuing messages and clearing them. + * This simulates the scenario where nextQueued() is attempting to process + * messages while a SequenceReset-GapFill operation clears them. + * + * Since InMemoryMessageQueue is designed for single-threaded access, + * this test uses synchronization to ensure only one operation at a time, + * but the order of operations is non-deterministic (either process first or clear first). + * * Acceptable outcomes: - * - 0 processed, 0 in queue: All messages were cleared before dequeue attempt + * - 0 processed, 0 in queue: All messages were cleared before processing attempt * - N processed, 0 in queue: N messages were processed, rest cleared * The key is that the queue should always be empty after both operations - * and the sum of processed + messages in queue should not exceed original count + * and all messages are accounted for (either processed or cleared, never both) */ @State @JCStressTest @@ -143,11 +152,11 @@ public void captureResult(org.openjdk.jcstress.infra.results.II_Result result) { private static final class MessageQueueWrapper { private final InMemoryMessageQueue queue; - private int processedCount; + private final AtomicInteger processedCount; public MessageQueueWrapper() { this.queue = new InMemoryMessageQueue(); - this.processedCount = 0; + this.processedCount = new AtomicInteger(0); // Pre-populate queue with messages (simulating out-of-sequence messages) // These messages have sequence numbers from 5 to 9 @@ -164,13 +173,14 @@ public MessageQueueWrapper() { /** * Simulates the nextQueued() method behavior - attempts to process * all queued messages in sequence order. + * Synchronized to simulate single-threaded Session behavior. */ public synchronized void processNextQueued() { // Try to process messages starting from sequence 5 for (int seqNum = 5; seqNum <= 9; seqNum++) { Message msg = queue.dequeue(seqNum); if (msg != null) { - processedCount++; + processedCount.incrementAndGet(); } } } @@ -178,6 +188,7 @@ public synchronized void processNextQueued() { /** * Simulates SequenceReset gap fill behavior - clears all messages * with sequence numbers less than the specified value. + * Synchronized to simulate single-threaded Session behavior. */ public synchronized void clearMessagesUpTo(int newSeqNum) { // Clear messages up to the new sequence number @@ -185,7 +196,7 @@ public synchronized void clearMessagesUpTo(int newSeqNum) { } public int getProcessedCount() { - return processedCount; + return processedCount.get(); } public int getQueueSize() { From b18cc6b276ec3e5a4fd359191522d319ad988437 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:20:07 +0000 Subject: [PATCH 7/8] Extract constants and clarify exclusive upper bound in comments Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../java/quickfix/MessageQueueClearStressTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java index aef51370e..475d9684d 100644 --- a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -151,6 +151,9 @@ public void captureResult(org.openjdk.jcstress.infra.results.II_Result result) { */ private static final class MessageQueueWrapper { + private static final int MIN_SEQ_NUM = 5; + private static final int MAX_SEQ_NUM = 9; + private final InMemoryMessageQueue queue; private final AtomicInteger processedCount; @@ -159,8 +162,7 @@ public MessageQueueWrapper() { this.processedCount = new AtomicInteger(0); // Pre-populate queue with messages (simulating out-of-sequence messages) - // These messages have sequence numbers from 5 to 9 - for (int i = 5; i <= 9; i++) { + for (int i = MIN_SEQ_NUM; i <= MAX_SEQ_NUM; i++) { try { Message msg = createMessage(i); queue.enqueue(i, msg); @@ -176,8 +178,8 @@ public MessageQueueWrapper() { * Synchronized to simulate single-threaded Session behavior. */ public synchronized void processNextQueued() { - // Try to process messages starting from sequence 5 - for (int seqNum = 5; seqNum <= 9; seqNum++) { + // Try to process all messages in the queue + for (int seqNum = MIN_SEQ_NUM; seqNum <= MAX_SEQ_NUM; seqNum++) { Message msg = queue.dequeue(seqNum); if (msg != null) { processedCount.incrementAndGet(); @@ -187,11 +189,11 @@ public synchronized void processNextQueued() { /** * Simulates SequenceReset gap fill behavior - clears all messages - * with sequence numbers less than the specified value. + * with sequence numbers strictly less than the specified value (exclusive). * Synchronized to simulate single-threaded Session behavior. */ public synchronized void clearMessagesUpTo(int newSeqNum) { - // Clear messages up to the new sequence number + // Clear messages with seqnum < newSeqNum (exclusive upper bound) queue.dequeueMessagesUpTo(newSeqNum); } From 3e1e3cc3dd92411be7ceddaeb6788a71a70d552d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 15 Feb 2026 15:22:07 +0000 Subject: [PATCH 8/8] Extract all magic numbers to named constants Co-authored-by: chrjohn <6644028+chrjohn@users.noreply.github.com> --- .../java/quickfix/MessageQueueClearStressTest.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java index 475d9684d..85f2f8200 100644 --- a/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java +++ b/quickfixj-stress-test/src/main/java/quickfix/MessageQueueClearStressTest.java @@ -88,7 +88,7 @@ public void processQueuedMessages() { // Actor 2: Thread trying to clear messages from queue (simulates SequenceReset gap fill) @Actor public void clearQueuedMessages() { - wrapper.clearMessagesUpTo(10); + wrapper.clearMessagesUpTo(MessageQueueWrapper.CLEAR_ALL_SEQ_NUM); } @Arbiter @@ -129,13 +129,13 @@ public void processMessages() { // Actor 2: First SequenceReset clearing messages @Actor public void firstSequenceReset() { - wrapper.clearMessagesUpTo(5); + wrapper.clearMessagesUpTo(MessageQueueWrapper.MIN_SEQ_NUM); } // Actor 3: Second SequenceReset clearing more messages @Actor public void secondSequenceReset() { - wrapper.clearMessagesUpTo(10); + wrapper.clearMessagesUpTo(MessageQueueWrapper.CLEAR_ALL_SEQ_NUM); } @Arbiter @@ -151,8 +151,11 @@ public void captureResult(org.openjdk.jcstress.infra.results.II_Result result) { */ private static final class MessageQueueWrapper { - private static final int MIN_SEQ_NUM = 5; - private static final int MAX_SEQ_NUM = 9; + // Sequence number range for pre-populated messages + static final int MIN_SEQ_NUM = 5; + static final int MAX_SEQ_NUM = 9; + // Sequence number to clear all messages (exclusive upper bound) + static final int CLEAR_ALL_SEQ_NUM = MAX_SEQ_NUM + 1; private final InMemoryMessageQueue queue; private final AtomicInteger processedCount;