Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions src/rdmacm/communication_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,12 +847,12 @@ impl Identifier {
}

let mut guard = DEVICE_LISTS.lock().unwrap();
let device_ctx = guard
.entry((*cm_id.as_ptr()).verbs as usize)
.or_insert(Arc::new(DeviceContext {
let device_ctx = guard.entry((*cm_id.as_ptr()).verbs as usize).or_insert_with(|| {
Arc::new(DeviceContext {
// Safe due to the is_null() check above.
context: NonNull::new((*cm_id.as_ptr()).verbs).unwrap(),
}));
})
});
Comment on lines +850 to +855

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better readability and to adhere to common Rust formatting conventions, it's recommended to format this chained method call across multiple lines. This makes the code easier to parse visually, especially with the closure.

Suggested change
let device_ctx = guard.entry((*cm_id.as_ptr()).verbs as usize).or_insert_with(|| {
Arc::new(DeviceContext {
// Safe due to the is_null() check above.
context: NonNull::new((*cm_id.as_ptr()).verbs).unwrap(),
}));
})
});
let device_ctx = guard
.entry((*cm_id.as_ptr()).verbs as usize)
.or_insert_with(|| {
Arc::new(DeviceContext {
// Safe due to the is_null() check above.
context: NonNull::new((*cm_id.as_ptr()).verbs).unwrap(),
})
});


Some(device_ctx.clone())
}
Expand Down Expand Up @@ -1156,4 +1156,45 @@ mod tests {
Err(_) => Ok(()),
}
}

#[test]
fn test_get_device_context_caches_correctly() -> Result<(), Box<dyn std::error::Error>> {
match EventChannel::new() {
Ok(channel) => {
let id = channel.create_id(PortSpace::Tcp)?;

let _ = id.resolve_addr(
None,
SocketAddr::from((IpAddr::from_str("127.0.0.1")?, 0)),
Duration::new(0, 200000000),
);

let event = channel.get_cm_event()?;
assert_eq!(event.event_type(), EventType::AddressResolved);

let ctx1 = id.get_device_context();
let ctx2 = id.get_device_context();
let ctx3 = id.get_device_context();

assert!(ctx1.is_some(), "First get_device_context should return Some");
assert!(ctx2.is_some(), "Second get_device_context should return Some");
assert!(ctx3.is_some(), "Third get_device_context should return Some");

assert!(
Arc::ptr_eq(&ctx1.clone().unwrap(), &ctx2.clone().unwrap()),
"ctx1 and ctx2 should point to the same DeviceContext"
);
assert!(
Arc::ptr_eq(&ctx2.clone().unwrap(), &ctx3.clone().unwrap()),
"ctx2 and ctx3 should point to the same DeviceContext"
);
Comment on lines +1183 to +1190

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To make the code more idiomatic and efficient, you can use as_ref() instead of clone() when comparing the Arc pointers. as_ref() borrows the content of the Option without incrementing the Arc's reference count, which is more efficient as you only need a reference for Arc::ptr_eq.

Suggested change
assert!(
Arc::ptr_eq(&ctx1.clone().unwrap(), &ctx2.clone().unwrap()),
"ctx1 and ctx2 should point to the same DeviceContext"
);
assert!(
Arc::ptr_eq(&ctx2.clone().unwrap(), &ctx3.clone().unwrap()),
"ctx2 and ctx3 should point to the same DeviceContext"
);
assert!(
Arc::ptr_eq(ctx1.as_ref().unwrap(), ctx2.as_ref().unwrap()),
"ctx1 and ctx2 should point to the same DeviceContext"
);
assert!(
Arc::ptr_eq(ctx2.as_ref().unwrap(), ctx3.as_ref().unwrap()),
"ctx2 and ctx3 should point to the same DeviceContext"
);


let ctx = ctx1.unwrap();
let _pd = ctx.alloc_pd()?;

Ok(())
},
Err(_) => Ok(()),
}
}
}
Loading