Skip to content

Instantly share code, notes, and snippets.

@punmechanic
Last active June 1, 2025 21:23
Show Gist options
  • Save punmechanic/93188256d48f30881dc1fb757284ade8 to your computer and use it in GitHub Desktop.
Save punmechanic/93188256d48f30881dc1fb757284ade8 to your computer and use it in GitHub Desktop.
how to do stupid C things in Rust
#include <pthread.h>
#include <stdlib.h>
struct State {
int acc;
};
void* run(void* arg) {
struct State* st = (struct State*) arg;
st->acc += 5;
}
int main() {
struct State state;
state.acc = 0;
pthread_t* ts = (pthread_t*)malloc(sizeof(pthread_t) * 5);
for (int i = 0; i < 5; i++) {
pthread_t t;
pthread_create(&t, NULL, run, &state);
}
for (int i = 0; i < 5; i++) {
pthread_join(ts[i], NULL);
}
return 0;
}
// If you really want to do multithreading stuff in C without Arc<Mutex<>>, or channels and want to do it exactly like C,
// you can do this.
//
// Yes, this feels jank. It feels jank because when you do it in C it is jank. But you're used to it being jank.
//
// please don't actually ever do this.
use std::mem::MaybeUninit;
use std::ptr::addr_of;
use std::thread::{spawn, JoinHandle};
struct State {
acc: u32
}
pub fn work_unsafe() {
let mut state = State { acc: 0 };
let ptr = addr_of!(state) as usize;
let mut handles: [MaybeUninit<JoinHandle<()>>; 5] = [
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit(),
MaybeUninit::uninit()
];
for i in 0..5 {
handles[i].write(spawn(move || {run(ptr)}));
}
for e in handles {
let handle = unsafe { e.assume_init() };
handle.join().expect("oop");
}
}
fn run(ptr: usize) {
let mut state = unsafe {
ptr as *mut State
};
unsafe {
(*state).acc += 5;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment