From 339785ac83c97abf32a81d4c4d70eeb6eda36794 Mon Sep 17 00:00:00 2001 From: Kevin Herron Date: Fri, 15 Nov 2024 15:09:13 -0800 Subject: [PATCH] Allow subclasses to provide a TransactionSequence (#89) Refactor to use subclassing instead of a constructor parameter for customizing the TransactionSequence. --- .../modbus/client/ModbusTcpClient.java | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/modbus/src/main/java/com/digitalpetri/modbus/client/ModbusTcpClient.java b/modbus/src/main/java/com/digitalpetri/modbus/client/ModbusTcpClient.java index 94d3758..281defd 100644 --- a/modbus/src/main/java/com/digitalpetri/modbus/client/ModbusTcpClient.java +++ b/modbus/src/main/java/com/digitalpetri/modbus/client/ModbusTcpClient.java @@ -35,25 +35,16 @@ public class ModbusTcpClient extends ModbusClient { private final Map promises = new ConcurrentHashMap<>(); + private final AtomicReference transactionSequence = new AtomicReference<>(); + private final ModbusClientConfig config; private final ModbusTcpClientTransport transport; - private final TransactionSequence transactionSequence; public ModbusTcpClient(ModbusClientConfig config, ModbusTcpClientTransport transport) { - this(config, transport, new DefaultTransactionSequence()); - } - - public ModbusTcpClient( - ModbusClientConfig config, - ModbusTcpClientTransport transport, - TransactionSequence transactionSequence - ) { - super(transport); this.config = config; this.transport = transport; - this.transactionSequence = transactionSequence; transport.receive(this::onFrameReceived); } @@ -116,7 +107,10 @@ public CompletionStage sendAsync(int unitId, ModbusRequestPdu } private CompletionStage sendBufferAsync(int unitId, ByteBuffer buffer) { - int transactionId = transactionSequence.next(); + TransactionSequence sequence = transactionSequence.updateAndGet( + ts -> ts != null ? ts : createTransactionSequence() + ); + int transactionId = sequence.next(); var header = new MbapHeader( transactionId, @@ -189,6 +183,16 @@ private void onFrameReceived(ModbusTcpFrame frame) { } } + /** + * Create and return the {@link TransactionSequence} that will be used to generate transaction + * ids. + * + * @return the {@link TransactionSequence} that will be used to generate transaction ids. + */ + protected TransactionSequence createTransactionSequence() { + return new DefaultTransactionSequence(); + } + /** * Create a new {@link ModbusTcpClient} using the given {@link ModbusTcpClientTransport} and a * {@link ModbusClientConfig} with the default values. @@ -239,6 +243,8 @@ public interface TransactionSequence { /** * Return the next 2-byte transaction identifier. Range is [0, 65535] by default. * + *

Implementations must be safe for use by multiple threads. + * * @return the next 2-byte transaction identifier. */ int next();