use libc::c_char;
pub struct SendSafePtr<T>(*mut T);
pub struct SendSafeCString(*mut c_char);
impl<T> SendSafePtr<T> {
pub unsafe fn new(ptr: *mut T) -> Self {
Self(ptr)
}
pub unsafe fn as_ptr(&self) -> *mut T {
self.0
}
pub unsafe fn as_const_ptr(&self) -> *const T {
self.0 as *const T
}
pub fn is_null(&self) -> bool {
self.0.is_null()
}
}
unsafe impl<T> Send for SendSafePtr<T> {}
unsafe impl<T> Sync for SendSafePtr<T> {}
impl SendSafeCString {
pub fn new(s: &str) -> Self {
Self(std::ffi::CString::new(s).unwrap().into_raw())
}
pub unsafe fn as_ptr(&self) -> *mut c_char {
self.0
}
}
impl Drop for SendSafeCString {
fn drop(&mut self) {
if !self.0.is_null() {
unsafe {
let _ = std::ffi::CString::from_raw(self.0);
}
}
}
}
unsafe impl Send for SendSafeCString {}
unsafe impl Sync for SendSafeCString {}
#[cfg(test)]
mod tests {
use super::*;
use libc::c_void;
use std::thread;
#[test]
fn test_send_safe_ptr_is_send() {
let ptr = unsafe { SendSafePtr::new(std::ptr::null_mut::<i32>()) };
thread::spawn(move || {
let _ = ptr;
})
.join()
.unwrap();
}
#[test]
fn test_send_safe_ptr_is_sync() {
let ptr = unsafe { SendSafePtr::new(std::ptr::null_mut::<i32>()) };
let handle = thread::spawn(|| {
let _ = ptr;
});
let _ = ptr;
handle.join().unwrap();
}
#[test]
fn test_send_safe_ptr_as_ptr() {
let raw_ptr: *mut i32 = std::ptr::null_mut();
let ptr = unsafe { SendSafePtr::new(raw_ptr) };
let retrieved_ptr = unsafe { ptr.as_ptr() };
assert_eq!(raw_ptr, retrieved_ptr);
}
#[test]
fn test_send_safe_ptr_as_const_ptr() {
let raw_ptr: *mut i32 = std::ptr::null_mut();
let ptr = unsafe { SendSafePtr::new(raw_ptr) };
let const_ptr = unsafe { ptr.as_const_ptr() };
assert_eq!(raw_ptr as *const i32, const_ptr);
}
#[test]
fn test_send_safe_ptr_with_c_void() {
let raw_ptr: *mut c_void = std::ptr::null_mut();
let ptr = unsafe { SendSafePtr::new(raw_ptr) };
let retrieved_ptr = unsafe { ptr.as_ptr() };
assert_eq!(raw_ptr, retrieved_ptr);
}
#[test]
fn test_send_safe_c_string_is_send() {
let c_string = SendSafeCString::new("Hello, World!");
thread::spawn(move || {
let _ = c_string;
})
.join()
.unwrap();
}
#[test]
fn test_send_safe_c_string_is_sync() {
let c_string = SendSafeCString::new("Hello, World!");
let handle = thread::spawn(|| {
let _ = c_string;
});
let _ = c_string;
handle.join().unwrap();
}
#[test]
fn test_send_safe_c_string_as_ptr() {
let c_string = SendSafeCString::new("Hello, World!");
let ptr = unsafe { c_string.as_ptr() };
assert!(!ptr.is_null());
}
#[test]
fn test_send_safe_c_string_cleanup() {
{
let _c_string = SendSafeCString::new("Test string");
} }
}