You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by mg...@apache.org on 2023/05/12 05:53:00 UTC

[avro] branch master updated: AVRO-3758: [Rust] use atomic types instead of static mut (#2225)

This is an automated email from the ASF dual-hosted git repository.

mgrigorov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new b86c63bae AVRO-3758: [Rust] use atomic types instead of static mut (#2225)
b86c63bae is described below

commit b86c63baeff4ef4a08c2559913d6e7c9d40d95b9
Author: Martin Grigorov <ma...@users.noreply.github.com>
AuthorDate: Fri May 12 08:52:53 2023 +0300

    AVRO-3758: [Rust] use atomic types instead of static mut (#2225)
    
    * AVRO-3758: [Rust] Use AtomicXyz types instead of static mutable ones
    
    Use AtomicBool for apache_avro::util::SERDE_HUMAN_READABLE
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
    
    * AVRO-3758: [Rust] Use AtomicXyz types instead of static mutable ones
    
    Use AtomicUsize for apache_avro::util::MAX_ALLOCATION_BYTES
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
    
    ---------
    
    Signed-off-by: Martin Tzvetanov Grigorov <mg...@apache.org>
---
 lang/rust/avro/src/de.rs   | 20 ++++++++------------
 lang/rust/avro/src/ser.rs  |  9 +++------
 lang/rust/avro/src/util.rs | 40 +++++++++++++++++++++-------------------
 3 files changed, 32 insertions(+), 37 deletions(-)

diff --git a/lang/rust/avro/src/de.rs b/lang/rust/avro/src/de.rs
index 691faae27..a1b52e6c5 100644
--- a/lang/rust/avro/src/de.rs
+++ b/lang/rust/avro/src/de.rs
@@ -651,6 +651,7 @@ pub fn from_value<'de, D: Deserialize<'de>>(value: &'de Value) -> Result<D, Erro
 mod tests {
     use pretty_assertions::assert_eq;
     use serde::Serialize;
+    use std::sync::atomic::Ordering;
     use uuid::Uuid;
 
     use super::*;
@@ -1227,32 +1228,27 @@ mod tests {
 
     #[test]
     fn avro_3747_human_readable_false() -> TestResult<()> {
-        // AVRO-3747: set serde's is_human_readable to false
         use serde::de::Deserializer as SerdeDeserializer;
 
-        unsafe {
-            crate::util::SERDE_HUMAN_READABLE = false;
-        }
+        let is_human_readable = false;
+        crate::util::SERDE_HUMAN_READABLE.store(is_human_readable, Ordering::Release);
 
-        let deser = Deserializer::new(&Value::Null);
+        let deser = &Deserializer::new(&Value::Null);
 
-        assert_eq!((&deser).is_human_readable(), false);
+        assert_eq!(deser.is_human_readable(), is_human_readable);
 
         Ok(())
     }
 
     #[test]
     fn avro_3747_human_readable_true() -> TestResult<()> {
-        // AVRO-3747: set serde's is_human_readable to true
         use serde::de::Deserializer as SerdeDeserializer;
 
-        unsafe {
-            crate::util::SERDE_HUMAN_READABLE = true;
-        }
+        crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release);
 
-        let deser = Deserializer::new(&Value::Null);
+        let deser = &Deserializer::new(&Value::Null);
 
-        assert!((&deser).is_human_readable());
+        assert!(deser.is_human_readable());
 
         Ok(())
     }
diff --git a/lang/rust/avro/src/ser.rs b/lang/rust/avro/src/ser.rs
index 1c7718ba7..2237c1d99 100644
--- a/lang/rust/avro/src/ser.rs
+++ b/lang/rust/avro/src/ser.rs
@@ -491,6 +491,7 @@ mod tests {
     use super::*;
     use pretty_assertions::assert_eq;
     use serde::{Deserialize, Serialize};
+    use std::sync::atomic::Ordering;
 
     #[derive(Debug, Deserialize, Serialize, Clone)]
     struct Test {
@@ -1007,9 +1008,7 @@ mod tests {
     fn avro_3747_human_readable_false() {
         use serde::ser::Serializer as SerdeSerializer;
 
-        unsafe {
-            crate::util::SERDE_HUMAN_READABLE = false;
-        }
+        crate::util::SERDE_HUMAN_READABLE.store(false, Ordering::Release);
 
         let ser = &mut Serializer {};
 
@@ -1020,9 +1019,7 @@ mod tests {
     fn avro_3747_human_readable_true() {
         use serde::ser::Serializer as SerdeSerializer;
 
-        unsafe {
-            crate::util::SERDE_HUMAN_READABLE = true;
-        }
+        crate::util::SERDE_HUMAN_READABLE.store(true, Ordering::Release);
 
         let ser = &mut Serializer {};
 
diff --git a/lang/rust/avro/src/util.rs b/lang/rust/avro/src/util.rs
index 695a1a6c7..d94acce7a 100644
--- a/lang/rust/avro/src/util.rs
+++ b/lang/rust/avro/src/util.rs
@@ -17,22 +17,29 @@
 
 use crate::{schema::Documentation, AvroResult, Error};
 use serde_json::{Map, Value};
-use std::{convert::TryFrom, i64, io::Read, sync::Once};
+use std::{
+    convert::TryFrom,
+    i64,
+    io::Read,
+    sync::{
+        atomic::{AtomicBool, AtomicUsize, Ordering},
+        Once,
+    },
+};
 
 /// Maximum number of bytes that can be allocated when decoding
 /// Avro-encoded values. This is a protection against ill-formed
 /// data, whose length field might be interpreted as enormous.
 /// See max_allocation_bytes to change this limit.
 pub const DEFAULT_MAX_ALLOCATION_BYTES: usize = 512 * 1024 * 1024;
-static mut MAX_ALLOCATION_BYTES: usize = DEFAULT_MAX_ALLOCATION_BYTES;
+static MAX_ALLOCATION_BYTES: AtomicUsize = AtomicUsize::new(DEFAULT_MAX_ALLOCATION_BYTES);
 static MAX_ALLOCATION_BYTES_ONCE: Once = Once::new();
 
 /// Whether to set serialization & deserialization traits
 /// as `human_readable` or not.
 /// See [set_serde_human_readable] to change this value.
-pub const DEFAULT_SERDE_HUMAN_READABLE: bool = true;
-// crate visible for testing
-pub(crate) static mut SERDE_HUMAN_READABLE: bool = DEFAULT_SERDE_HUMAN_READABLE;
+// crate-visible for testing
+pub(crate) static SERDE_HUMAN_READABLE: AtomicBool = AtomicBool::new(true);
 static SERDE_HUMAN_READABLE_ONCE: Once = Once::new();
 
 pub trait MapHelper {
@@ -140,12 +147,10 @@ fn decode_variable<R: Read>(reader: &mut R) -> AvroResult<u64> {
 /// to set the limit either when calling this method, or when decoding for
 /// the first time.
 pub fn max_allocation_bytes(num_bytes: usize) -> usize {
-    unsafe {
-        MAX_ALLOCATION_BYTES_ONCE.call_once(|| {
-            MAX_ALLOCATION_BYTES = num_bytes;
-        });
-        MAX_ALLOCATION_BYTES
-    }
+    MAX_ALLOCATION_BYTES_ONCE.call_once(|| {
+        MAX_ALLOCATION_BYTES.store(num_bytes, Ordering::Release);
+    });
+    MAX_ALLOCATION_BYTES.load(Ordering::Acquire)
 }
 
 pub fn safe_len(len: usize) -> AvroResult<usize> {
@@ -169,17 +174,14 @@ pub fn safe_len(len: usize) -> AvroResult<usize> {
 /// library leverages [`std::sync::Once`](https://doc.rust-lang.org/std/sync/struct.Once.html)
 /// to set the limit either when calling this method, or when decoding for
 /// the first time.
-pub fn set_serde_human_readable(human_readable: bool) -> bool {
-    unsafe {
-        SERDE_HUMAN_READABLE_ONCE.call_once(|| {
-            SERDE_HUMAN_READABLE = human_readable;
-        });
-        SERDE_HUMAN_READABLE
-    }
+pub fn set_serde_human_readable(human_readable: bool) {
+    SERDE_HUMAN_READABLE_ONCE.call_once(|| {
+        SERDE_HUMAN_READABLE.store(human_readable, Ordering::Release);
+    });
 }
 
 pub(crate) fn is_human_readable() -> bool {
-    unsafe { SERDE_HUMAN_READABLE }
+    SERDE_HUMAN_READABLE.load(Ordering::Acquire)
 }
 
 #[cfg(test)]