From aa257c00540955707e2f2d37d0b6b99d9dd0b8fc Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Mon, 12 Feb 2024 15:53:06 +0100 Subject: [PATCH] fix(client): change to `AtomicU64` to `AtomicUsize` (#1293) * fix(client): change to `AtomicU64` to `AtomicUsize` Some targets may not support AtomicU64. This PR moves to `AtomicUsize` instead to support more targets. * Update core/src/client/mod.rs * fix benches --- benches/helpers.rs | 6 +++--- core/src/client/mod.rs | 28 ++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/benches/helpers.rs b/benches/helpers.rs index 20a22c8eb7..c02852392c 100644 --- a/benches/helpers.rs +++ b/benches/helpers.rs @@ -50,13 +50,13 @@ pub async fn http_server(handle: tokio::runtime::Handle) -> (String, jsonrpc_htt /// Run jsonrpc WebSocket server for benchmarks. #[cfg(feature = "jsonrpc-crate")] pub async fn ws_server(handle: tokio::runtime::Handle) -> (String, jsonrpc_ws_server::Server) { - use std::sync::atomic::{AtomicU64, Ordering}; + use std::sync::atomic::{AtomicUsize, Ordering}; use jsonrpc_pubsub::{PubSubHandler, Session, Subscriber, SubscriptionId}; use jsonrpc_ws_server::jsonrpc_core::*; use jsonrpc_ws_server::*; - static ID: AtomicU64 = AtomicU64::new(0); + static ID: AtomicUsize = AtomicUsize::new(0); let handle2 = handle.clone(); @@ -78,7 +78,7 @@ pub async fn ws_server(handle: tokio::runtime::Handle) -> (String, jsonrpc_ws_se SUB_METHOD_NAME, (SUB_METHOD_NAME, move |_params: Params, _, subscriber: Subscriber| { handle2.spawn(async move { - let id = ID.fetch_add(1, Ordering::Relaxed); + let id = ID.fetch_add(1, Ordering::Relaxed).try_into().unwrap(); let sink = subscriber.assign_id(SubscriptionId::Number(id)).unwrap(); // NOTE(niklasad1): the way jsonrpc works this is the only way to get this working // -> jsonrpc responds to the request in background so not possible to know when the request diff --git a/core/src/client/mod.rs b/core/src/client/mod.rs index 6b91774fe9..0bea886b6d 100644 --- a/core/src/client/mod.rs +++ b/core/src/client/mod.rs @@ -37,7 +37,7 @@ pub use error::Error; use std::fmt; use std::ops::Range; use std::pin::Pin; -use std::sync::atomic::{AtomicU64, Ordering}; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use std::task; @@ -396,7 +396,7 @@ pub struct RequestIdManager { /// Max concurrent pending requests allowed. max_concurrent_requests: usize, /// Get the next request ID. - current_id: AtomicU64, + current_id: CurrentId, /// Request ID type. id_kind: IdKind, } @@ -404,7 +404,7 @@ pub struct RequestIdManager { impl RequestIdManager { /// Create a new `RequestIdGuard` with the provided concurrency limit. pub fn new(limit: usize, id_kind: IdKind) -> Self { - Self { current_pending: Arc::new(()), max_concurrent_requests: limit, current_id: AtomicU64::new(0), id_kind } + Self { current_pending: Arc::new(()), max_concurrent_requests: limit, current_id: CurrentId::new(), id_kind } } fn get_slot(&self) -> Result, Error> { @@ -421,7 +421,7 @@ impl RequestIdManager { /// Fails if request limit has been exceeded. pub fn next_request_id(&self) -> Result>, Error> { let rc = self.get_slot()?; - let id = self.id_kind.into_id(self.current_id.fetch_add(1, Ordering::SeqCst)); + let id = self.id_kind.into_id(self.current_id.next()); Ok(RequestIdGuard { _rc: rc, id }) } @@ -432,8 +432,8 @@ impl RequestIdManager { /// Fails if request limit has been exceeded. pub fn next_request_two_ids(&self) -> Result, Id<'static>)>, Error> { let rc = self.get_slot()?; - let id1 = self.id_kind.into_id(self.current_id.fetch_add(1, Ordering::SeqCst)); - let id2 = self.id_kind.into_id(self.current_id.fetch_add(1, Ordering::SeqCst)); + let id1 = self.id_kind.into_id(self.current_id.next()); + let id2 = self.id_kind.into_id(self.current_id.next()); Ok(RequestIdGuard { _rc: rc, id: (id1, id2) }) } @@ -487,6 +487,22 @@ impl IdKind { } } +#[derive(Debug)] +struct CurrentId(AtomicUsize); + +impl CurrentId { + fn new() -> Self { + CurrentId(AtomicUsize::new(0)) + } + + fn next(&self) -> u64 { + self.0 + .fetch_add(1, Ordering::Relaxed) + .try_into() + .expect("usize -> u64 infallible, there are no CPUs > 64 bits; qed") + } +} + /// Generate a range of IDs to be used in a batch request. pub fn generate_batch_id_range(guard: &RequestIdGuard, len: u64) -> Result, Error> { let id_start = guard.inner().try_parse_inner_as_number()?;