Skip to content

Instantly share code, notes, and snippets.

@randomPoison
Last active August 30, 2016 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save randomPoison/e8b9bf35611447614e373a1a00f2f22b to your computer and use it in GitHub Desktop.
Save randomPoison/e8b9bf35611447614e373a1a00f2f22b to your computer and use it in GitHub Desktop.
Version that only uses a hand-rolled macro to do magic.
#![feature(fnbox)]
use std::boxed::FnBox;
/// Represents a single unit of work that needs doing.
///
/// Erases type information about the work that needs to be done, reducing it
/// to a single function invocation.
struct Worker(Box<FnBox()>);
impl Worker {
/// Creates a new unit of work
unsafe fn new<T: 'static>(value: T, out: &mut Option<T>) -> Worker {
let out_ptr = out as *mut _;
let work_proc = move || {
*out_ptr = Some(value);
};
Worker(Box::new(work_proc))
}
}
fn finish_all<I: IntoIterator<Item = Worker>>(workers: I) {
for worker in workers {
worker.0();
}
}
macro_rules! do_work {
($work_0: expr, $work_1: expr, $work_2: expr) => {
{
let mut result_0 = None;
let mut result_1 = None;
let mut result_2 = None;
let worker_0 = unsafe { Worker::new($work_0, &mut result_0) };
let worker_1 = unsafe { Worker::new($work_1, &mut result_1) };
let worker_2 = unsafe { Worker::new($work_2, &mut result_2) };
finish_all(vec![worker_0, worker_1, worker_2]);
(result_0.unwrap(), result_1.unwrap(), result_2.unwrap())
}
};
($work_0: expr, $work_1: expr) => {
{
let mut result_0 = None;
let mut result_1 = None;
let worker_0 = unsafe { Worker::new($work_0, &mut result_0) };
let worker_1 = unsafe { Worker::new($work_1, &mut result_1) };
finish_all(vec![worker_0, worker_1]);
(result_0.unwrap(), result_1.unwrap())
}
};
}
fn main() {
let result = do_work!(1, true, 3.14);
println!("{:?}", result);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment