Skip to content

Commit

Permalink
Use LazyLock instead of OnceLock
Browse files Browse the repository at this point in the history
  • Loading branch information
erikgrinaker committed Feb 7, 2025
1 parent dae2a75 commit d757220
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 21 deletions.
19 changes: 8 additions & 11 deletions src/encoding/bincode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,31 @@
//! than DefaultOptions (variable) -- this module always uses DefaultOptions.
use std::io::{Read, Write};
use std::sync::OnceLock;
use std::sync::LazyLock;

use bincode::Options as _;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};

use crate::error::{Error, Result};

/// Returns the default Bincode options, initialized on first use.
fn bincode() -> &'static bincode::DefaultOptions {
static BINCODE: OnceLock<bincode::DefaultOptions> = OnceLock::new();
BINCODE.get_or_init(bincode::DefaultOptions::new)
}
/// Default Bincode options. Unlike e.g. `bincode::serialize()`, this uses varint encoding.
static BINCODE: LazyLock<bincode::DefaultOptions> = LazyLock::new(bincode::DefaultOptions::new);

/// Deserializes a value using Bincode.
pub fn deserialize<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T> {
Ok(bincode().deserialize(bytes)?)
Ok(BINCODE.deserialize(bytes)?)
}

/// Deserializes a value from a reader using Bincode.
pub fn deserialize_from<R: Read, T: DeserializeOwned>(reader: R) -> Result<T> {
Ok(bincode().deserialize_from(reader)?)
Ok(BINCODE.deserialize_from(reader)?)
}

/// Deserializes a value from a reader using Bincode, or returns None if the
/// reader is closed.
pub fn maybe_deserialize_from<R: Read, T: DeserializeOwned>(reader: R) -> Result<Option<T>> {
match bincode().deserialize_from(reader) {
match BINCODE.deserialize_from(reader) {
Ok(v) => Ok(Some(v)),
Err(e) => match *e {
bincode::ErrorKind::Io(e) => match e.kind() {
Expand All @@ -53,10 +50,10 @@ pub fn maybe_deserialize_from<R: Read, T: DeserializeOwned>(reader: R) -> Result
pub fn serialize<T: Serialize>(value: &T) -> Vec<u8> {
// Panic on serialization failures, as this is typically an issue with the
// provided data structure.
bincode().serialize(value).expect("bincode serialization failed")
BINCODE.serialize(value).expect("bincode serialization failed")
}

/// Serializes a value to a writer using Bincode.
pub fn serialize_into<W: Write, T: Serialize>(writer: W, value: &T) -> Result<()> {
Ok(bincode().serialize_into(writer, value)?)
Ok(BINCODE.serialize_into(writer, value)?)
}
25 changes: 15 additions & 10 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,42 @@

mod testcluster;

use itertools::Itertools as _;
use std::collections::HashMap;
use std::error::Error;
use std::fmt::Write as _;
use std::{collections::HashMap, error::Error};
use std::path::Path;
use std::sync::{LazyLock, Mutex};

use itertools::Itertools as _;
use test_each_file::test_each_path;

use testcluster::TestCluster;
use toydb::{Client, StatementResult};

// Run goldenscript tests in tests/scripts.
test_each_path! { in "tests/scripts" => test_goldenscript }

fn test_goldenscript(path: &std::path::Path) {
fn test_goldenscript(path: &Path) {
// We can't run tests concurrently, because the test clusters end up using
// the same ports (and we don't want to run a ton of them). We can't use the
// #[serial] macro either, since it doesn't work with test_each_path. Just
// use a mutex to serialize them, and ignore any poisoning.
static MUTEX: std::sync::OnceLock<std::sync::Mutex<()>> = std::sync::OnceLock::new();
let mutex = MUTEX.get_or_init(|| std::sync::Mutex::new(()));
let _guard = mutex.lock().unwrap_or_else(|error| error.into_inner());
// the same ports. We also don't want to run a bunch of them concurrently.
// We can't use the #[serial_test] macro either, since it doesn't work with
// test_each_path. Just use a mutex to serialize them.
static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(Mutex::default);
let _guard = MUTEX.lock().ok(); // ignore poisoning

goldenscript::run(&mut Runner::new(), path).expect("goldenscript failed")
}

/// Runs Raft goldenscript tests. See run() for available commands.
#[derive(Default)]
struct Runner {
cluster: Option<TestCluster>,
clients: HashMap<String, Client>,
}

impl Runner {
fn new() -> Self {
Self { cluster: None, clients: HashMap::new() }
Self::default()
}

/// Fetches a client for the given prefix, or creates a new one.
Expand Down

0 comments on commit d757220

Please sign in to comment.