leapfrog
leapfrog copied to clipboard
Inserting fails unpredictably with structs & alignment
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!");
}
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.
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