use mpi_sys::MPI_Comm;
use crate::{ffi, topology::comm_is_inter, traits::AsRaw};
pub enum CommunicatorHandle {
SelfComm,
World,
User(MPI_Comm),
Parent(MPI_Comm),
InterComm(MPI_Comm),
}
impl CommunicatorHandle {
pub unsafe fn try_from_raw(raw: MPI_Comm) -> Option<CommunicatorHandle> {
if raw == ffi::RSMPI_COMM_NULL {
None
} else if raw == ffi::RSMPI_COMM_WORLD {
Some(CommunicatorHandle::World)
} else if raw == ffi::RSMPI_COMM_SELF {
Some(CommunicatorHandle::SelfComm)
} else {
if comm_is_inter(raw) {
let mut parent_comm = ffi::RSMPI_COMM_NULL;
ffi::MPI_Comm_get_parent(&mut parent_comm);
if raw == parent_comm {
Some(CommunicatorHandle::Parent(raw))
} else {
Some(CommunicatorHandle::InterComm(raw))
}
} else {
Some(CommunicatorHandle::User(raw))
}
}
}
pub unsafe fn simple_comm_from_raw(raw: MPI_Comm) -> CommunicatorHandle {
debug_assert_ne!(raw, ffi::RSMPI_COMM_NULL);
debug_assert_ne!(raw, ffi::RSMPI_COMM_WORLD);
debug_assert_ne!(raw, ffi::RSMPI_COMM_SELF);
debug_assert!(!comm_is_inter(raw));
CommunicatorHandle::User(raw)
}
pub unsafe fn inter_comm_from_raw(raw: MPI_Comm) -> CommunicatorHandle {
debug_assert_ne!(raw, ffi::RSMPI_COMM_NULL);
debug_assert!(comm_is_inter(raw));
CommunicatorHandle::InterComm(raw)
}
#[allow(dead_code)]
pub unsafe fn parent_comm_from_raw(raw: MPI_Comm) -> CommunicatorHandle {
debug_assert_ne!(raw, ffi::RSMPI_COMM_NULL);
debug_assert!({
let mut parent = ffi::RSMPI_COMM_NULL;
ffi::MPI_Comm_get_parent(&mut parent);
raw == parent
});
CommunicatorHandle::Parent(raw)
}
#[allow(dead_code)]
pub fn is_inter_comm(&self) -> bool {
match self {
CommunicatorHandle::SelfComm
| CommunicatorHandle::World
| CommunicatorHandle::User(_) => false,
CommunicatorHandle::Parent(_) | CommunicatorHandle::InterComm(_) => true,
}
}
}
impl Drop for CommunicatorHandle {
fn drop(&mut self) {
match self {
CommunicatorHandle::SelfComm => { }
CommunicatorHandle::World => { }
CommunicatorHandle::Parent(_) => {
}
CommunicatorHandle::User(handle) => unsafe {
ffi::MPI_Comm_free(handle);
assert_eq!(*handle, ffi::RSMPI_COMM_NULL);
},
CommunicatorHandle::InterComm(handle) => unsafe {
ffi::MPI_Comm_disconnect(handle);
assert_eq!(*handle, ffi::RSMPI_COMM_NULL);
},
}
}
}
unsafe impl AsRaw for CommunicatorHandle {
type Raw = MPI_Comm;
fn as_raw(&self) -> Self::Raw {
match self {
CommunicatorHandle::SelfComm => unsafe { ffi::RSMPI_COMM_SELF },
CommunicatorHandle::World => unsafe { ffi::RSMPI_COMM_WORLD },
CommunicatorHandle::Parent(handle) => *handle,
CommunicatorHandle::User(handle) => *handle,
CommunicatorHandle::InterComm(handle) => *handle,
}
}
}
pub trait AsHandle: AsRaw<Raw = MPI_Comm> {
fn as_handle(&self) -> &CommunicatorHandle;
}