19
19
import java .util .concurrent .ExecutionException ;
20
20
import java .util .concurrent .TimeUnit ;
21
21
import java .util .concurrent .TimeoutException ;
22
- import java .util .concurrent .atomic .AtomicInteger ;
22
+ import java .util .concurrent .atomic .AtomicReference ;
23
23
import java .util .function .Consumer ;
24
24
import org .slf4j .Logger ;
25
25
import org .slf4j .LoggerFactory ;
@@ -33,17 +33,27 @@ public class ModbusTcpClient extends ModbusClient {
33
33
34
34
private final Logger logger = LoggerFactory .getLogger (getClass ());
35
35
36
- private final TransactionSequence transactionSequence = new TransactionSequence ();
37
36
private final Map <Integer , ResponsePromise > promises = new ConcurrentHashMap <>();
38
37
39
- private final ModbusTcpClientTransport transport ;
40
38
private final ModbusClientConfig config ;
39
+ private final ModbusTcpClientTransport transport ;
40
+ private final TransactionSequence transactionSequence ;
41
41
42
42
public ModbusTcpClient (ModbusClientConfig config , ModbusTcpClientTransport transport ) {
43
+ this (config , transport , new DefaultTransactionSequence ());
44
+ }
45
+
46
+ public ModbusTcpClient (
47
+ ModbusClientConfig config ,
48
+ ModbusTcpClientTransport transport ,
49
+ TransactionSequence transactionSequence
50
+ ) {
51
+
43
52
super (transport );
44
53
45
54
this .config = config ;
46
55
this .transport = transport ;
56
+ this .transactionSequence = transactionSequence ;
47
57
48
58
transport .receive (this ::onFrameReceived );
49
59
}
@@ -224,12 +234,44 @@ private record ResponsePromise(
224
234
TimeoutHandle timeout
225
235
) {}
226
236
227
- static class TransactionSequence {
237
+ public interface TransactionSequence {
238
+
239
+ /**
240
+ * Return the next 2-byte transaction identifier. Range is [0, 65535] by default.
241
+ *
242
+ * @return the next 2-byte transaction identifier.
243
+ */
244
+ int next ();
245
+ }
246
+
247
+ public static class DefaultTransactionSequence implements TransactionSequence {
228
248
229
- private final AtomicInteger transactionId = new AtomicInteger (0 );
249
+ private final int low ;
250
+ private final int high ;
230
251
231
- int next () {
232
- return transactionId .getAndIncrement () & 0xFFFF ;
252
+ private final AtomicReference <Integer > transactionId = new AtomicReference <>(0 );
253
+
254
+ public DefaultTransactionSequence () {
255
+ this (0 , 65535 );
256
+ }
257
+
258
+ public DefaultTransactionSequence (int low , int high ) {
259
+ this .low = low ;
260
+ this .high = high ;
261
+
262
+ transactionId .set (low );
263
+ }
264
+
265
+ @ Override
266
+ public int next () {
267
+ while (true ) {
268
+ Integer id = transactionId .get ();
269
+ Integer nextId = id >= high ? low : id + 1 ;
270
+
271
+ if (transactionId .compareAndSet (id , nextId )) {
272
+ return id ;
273
+ }
274
+ }
233
275
}
234
276
235
277
}
0 commit comments