-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tcp client: Use non-atomic type for internal transaction id (#285)
- Loading branch information
Showing
1 changed file
with
31 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,50 @@ | ||
// SPDX-FileCopyrightText: Copyright (c) 2017-2024 slowtec GmbH <[email protected]> | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
||
use std::{ | ||
fmt, io, | ||
sync::atomic::{AtomicU16, Ordering}, | ||
}; | ||
use std::{fmt, io}; | ||
|
||
use futures_util::{SinkExt as _, StreamExt as _}; | ||
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt as _}; | ||
use tokio_util::codec::Framed; | ||
|
||
use crate::{ | ||
codec, | ||
frame::{tcp::*, *}, | ||
frame::{ | ||
tcp::{Header, RequestAdu, ResponseAdu, TransactionId, UnitId}, | ||
RequestPdu, ResponsePdu, | ||
}, | ||
service::verify_response_header, | ||
slave::*, | ||
ProtocolError, Result, | ||
ExceptionResponse, ProtocolError, Request, Response, Result, | ||
}; | ||
|
||
const INITIAL_TRANSACTION_ID: TransactionId = 0; | ||
|
||
#[derive(Debug)] | ||
struct TransactionIdGenerator { | ||
next_transaction_id: TransactionId, | ||
} | ||
|
||
impl TransactionIdGenerator { | ||
const fn new() -> Self { | ||
Self { | ||
next_transaction_id: INITIAL_TRANSACTION_ID, | ||
} | ||
} | ||
|
||
fn next(&mut self) -> TransactionId { | ||
let next_transaction_id = self.next_transaction_id; | ||
self.next_transaction_id = next_transaction_id.wrapping_add(1); | ||
next_transaction_id | ||
} | ||
} | ||
|
||
/// Modbus TCP client | ||
#[derive(Debug)] | ||
pub(crate) struct Client<T> { | ||
framed: Option<Framed<T, codec::tcp::ClientCodec>>, | ||
transaction_id_generator: TransactionIdGenerator, | ||
unit_id: UnitId, | ||
transaction_id: AtomicU16, | ||
} | ||
|
||
impl<T> Client<T> | ||
|
@@ -34,31 +53,24 @@ where | |
{ | ||
pub(crate) fn new(transport: T, slave: Slave) -> Self { | ||
let framed = Framed::new(transport, codec::tcp::ClientCodec::new()); | ||
let transaction_id_generator = TransactionIdGenerator::new(); | ||
let unit_id: UnitId = slave.into(); | ||
let transaction_id = AtomicU16::new(INITIAL_TRANSACTION_ID); | ||
Self { | ||
framed: Some(framed), | ||
transaction_id_generator, | ||
unit_id, | ||
transaction_id, | ||
} | ||
} | ||
|
||
fn next_transaction_id(&self) -> TransactionId { | ||
let transaction_id = self.transaction_id.load(Ordering::Relaxed); | ||
self.transaction_id | ||
.store(transaction_id.wrapping_add(1), Ordering::Relaxed); | ||
transaction_id | ||
} | ||
|
||
fn next_request_hdr(&self, unit_id: UnitId) -> Header { | ||
let transaction_id = self.next_transaction_id(); | ||
fn next_request_hdr(&mut self, unit_id: UnitId) -> Header { | ||
let transaction_id = self.transaction_id_generator.next(); | ||
Header { | ||
transaction_id, | ||
unit_id, | ||
} | ||
} | ||
|
||
fn next_request_adu<'a, R>(&self, req: R) -> RequestAdu<'a> | ||
fn next_request_adu<'a, R>(&mut self, req: R) -> RequestAdu<'a> | ||
where | ||
R: Into<RequestPdu<'a>>, | ||
{ | ||
|