How do I - Rust + C lib + threads

⚓ Rust    📅 2026-02-20    👤 surdeus    👁️ 5      

surdeus

Hello. I'm new to Rust. It fries my brain when I try to understand it. Here's some code I'd like to make properly idiomatic (and by extension, actually compile..) All feedback welcome, including "take off and nuke it from orbit" if it's really that bad.

Note: The code will not compile as is. It needs.. help..

#[allow(unused)]
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
use std::collections::VecDeque;
use std::time::Duration;
#[allow(unused)]
use std::ptr;

// a wrapper for a pointer to a Thing allocated by a C library
struct LibThing<T>(*mut T);
// or possibly..?
//struct LibThing<T>(Mutex<*mut T>);

impl<T> LibThing<T> {
    pub fn new() -> Self {
        // call C lib to allocate a new Thing
        Self(ptr::null_mut())
    }
    
    // Thing should never be accessed by two threads at once
    // do we do this here, or externally using Mutex<LibThing> ?
    pub fn lock() {}
    
    // requires exclusive access for duration
    pub fn transform(&mut self) {
        // call C lib to mutate the Thing in some way
    }
    
    #[allow(unused)]
    // Source and Dest should be exclusively accessed by a single thread for duration
    pub fn copy_to(&self, dst: &mut LibThing<T>) {
        // call C lib to copy data from Thing A to Thing B
    }
}

// Thing can be safely freed by the thread that allocated it
impl<T> Drop for LibThing<T> {
    fn drop(&mut self) {
        // call C lib to free a Thing
    }
}

// !Send: it is not desirable for any other thread to free a Thing than the thread that allocated it
// Sync: a source Thing will be shared with multiple worker threads,
//  but each worker must have exclusively access while reading from it
//unsafe impl<T> Sync for LibThing<T> {}

fn main() {
    const max_threads: u8 = 10;
    let mut threads: VecDeque<JoinHandle<()>> = VecDeque::new();
    // simulate loading a source Thing from a file
    let source_thing = LibThing::<i8>::new();
    let mutex = Mutex::new(source_thing);
    let shared_mutex = &mutex;
    
    for i in 0..max_threads {
        let handle = thread::spawn(move || {
            println!("t{i} spawned");
            println!("t{i} get source Thing mutex");
            let guard = shared_mutex.lock().expect("mutex poisoned");
            println!("t{i} got mutex, simulate work..");
            let mut dst = LibThing::<i8>::new();
            guard.copy_to(&mut dst);
            thread::sleep(Duration::from_secs(1));
            println!("t{i} release mutex");
            //drop(guard);
        });
        threads.push_back(handle);
    }
    
    for i in threads.into_iter() {
        let _ = i.join();
    }
}

6 posts - 3 participants

Read full topic

🏷️ Rust_feed