Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inserting fails unpredictably with structs & alignment #14

Open
otisdog8 opened this issue Dec 18, 2023 · 2 comments
Open

Inserting fails unpredictably with structs & alignment #14

otisdog8 opened this issue Dec 18, 2023 · 2 comments

Comments

@otisdog8
Copy link

For some reason, inserting will either freeze or will not properly insert if the struct isn't a multiple of 64 bits in size.

See code below:

If you change b to a u64, the code works as expected.

use std::fmt::{Debug};
use lazy_static::lazy_static;
use leapfrog::{LeapMap, Value};


#[derive(Debug, Copy, Clone, PartialEq)]
struct TestStruct {
    a: u64,
    b: u32,
}

macro_rules! value_impl {
    ($type:ty, $redirect_expr:expr, $null_expr:expr) => {
        impl Value for $type {
            #[inline]
            fn is_redirect(&self) -> bool {
                *self == $redirect_expr
            }
            #[inline]
            fn is_null(&self) -> bool {
                *self == $null_expr
            }
            #[inline]
            fn redirect() -> Self {
                $redirect_expr
            }
            #[inline]
            fn null() -> Self {
                $null_expr
            }
        }
    };
}

value_impl!(TestStruct, TestStruct {a: u64::MAX, b: 0 }, TestStruct {a: u64::MAX - 1, b: 0});

lazy_static! {
    static ref A_MAP: LeapMap<u64, TestStruct> = LeapMap::new();
    static ref B_MAP: LeapMap<u64, u64> = LeapMap::new();
}

fn main() {
    let C_MAP: LeapMap<u64, TestStruct> = LeapMap::new();
    let D_MAP: LeapMap<u64, u64> = LeapMap::new();

    let mut key = 0;
    for i in 0..100 {
        key += 1;
        let result = A_MAP.insert(key, TestStruct { a: key, b: 0});
        println!("Inserting new key {} sz {} res {:?}", key, A_MAP.len(), result);
        let result = C_MAP.insert(key, TestStruct { a: key, b: 0});
        println!("Inserting new key {} sz {} res {:?}", key, C_MAP.len(), result);
        let result = B_MAP.insert(key, key);
        println!("Inserting new key {} sz {} res {:?}", key, B_MAP.len(), result);
        let result = D_MAP.insert(key, key);
        println!("Inserting new key {} sz {} res {:?}", key, D_MAP.len(), result);

    }

    println!("Hello, world!");
}
@robclu
Copy link
Owner

robclu commented Dec 19, 2023

Hi,

Thanks for this. I'm not immediately sure what's causing this, but I will try and get to it as soon as possible. Mostly likely this weekend.

@cavemanloverboy
Copy link

cavemanloverboy commented Jan 24, 2024

The problem also exists for keys, and even for those that are a multiple of 64 bits. See this example:

use leapfrog::{LeapMap, Value};

pub type Uuid = u128;
fn main() {
    let map = LeapMap::<Uuid, Token>::new();

    let key = Uuid::MAX / 2;
    let value = Token {
        token_type: TokenType::One,
        index: 0,
    };
    map.insert(key, value);

    let v = map.get(&key);
    println!("{:?}", v.map(|mut r| r.value()));
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Token {
    token_type: TokenType,
    index: usize,
}

#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum TokenType {
    One,
    Two,

    Redirect = u32::MAX - 1,
    Null = u32::MAX,
}

impl Value for Token {
    fn null() -> Token {
        Token {
            token_type: TokenType::Null,
            index: usize::MAX,
        }
    }
    fn redirect() -> Self {
        Token {
            token_type: TokenType::Redirect,
            index: usize::MAX - 1,
        }
    }

    fn is_null(&self) -> bool {
        *self == Self::null()
    }

    fn is_redirect(&self) -> bool {
        *self == Self::redirect()
    }
}

This always fails for me (on ARM — a macbook with M2 Max). However, if I switch Uuid to a u64 it works.

edit: Failing in this context means that the get returns None, despite having just inserted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants