Skip to content

Instantly share code, notes, and snippets.

@nwin

nwin/test.rs Secret

Last active August 29, 2015 14:16
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 nwin/db3138f6d421bf2e6189 to your computer and use it in GitHub Desktop.
Save nwin/db3138f6d421bf2e6189 to your computer and use it in GitHub Desktop.
#![feature(std_misc)]
#![allow(raw_pointer_derive)]
#![feature(box_syntax)]
use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::thread::spawn;
use std::thunk::Invoke;
struct Listener(Box<for<'r> Invoke<(&'r AsyncResponseListener)> + Send>);
impl Listener {
fn new<F: FnOnce(&AsyncResponseListener) + Send + 'static>(f: F) -> Listener { Listener(box f) }
}
trait AsyncResponseTarget {
fn invoke_with_listener(&self, f: Listener);
}
trait AsyncResponseListener {
fn foo(&self);
}
fn resource_task(rx: Receiver<Box<AsyncResponseTarget+Send>>) {
let target = rx.recv().unwrap();
target.invoke_with_listener(Listener::new(move |listener| {
listener.foo();
}));
}
struct FooContext {
foo_ptr: *const MainThreadFoo,
}
unsafe impl Send for FooContext {}
impl AsyncResponseListener for FooContext {
fn foo(&self) {
let foo = unsafe { &*self.foo_ptr };
println!("n is {}", foo.n);
}
}
impl Drop for FooContext {
fn drop(&mut self) {
let _foo: Box<MainThreadFoo> = unsafe { mem::transmute(self.foo_ptr) };
}
}
struct OffThreadListener {
main_thread_foo: Arc<Mutex<FooContext>>,
main_tx: Sender<Box<Runnable+Send>>,
}
impl AsyncResponseTarget for OffThreadListener {
fn invoke_with_listener(&self, f: Listener) {
self.main_tx.send(Box::new(MainThreadInvoke {
foo: self.main_thread_foo.clone(),
f: f,
})).unwrap();
}
}
trait Runnable {
fn handler(self: Box<Self>);
}
struct MainThreadInvoke {
foo: Arc<Mutex<FooContext>>,
f: Listener,
}
impl<'a> Runnable for MainThreadInvoke {
fn handler(self: Box<Self>) {
let this = *self;
let foo = this.foo.lock().unwrap();
let Listener(f) = this.f;
f.invoke(&*foo);
}
}
struct MainThreadFoo {
n: u64,
_n2: u64,
}
fn main() {
let (resource_tx, resource_rx) = channel();
let (main_tx, main_rx) = channel();
spawn(move || {
resource_task(resource_rx);
});
let foo = Box::new(MainThreadFoo { n: 1337, _n2: 0 });
let foo_context = FooContext {
foo_ptr: unsafe { mem::transmute(foo) },
};
let listener = OffThreadListener {
main_thread_foo: Arc::new(Mutex::new(foo_context)),
main_tx: main_tx,
};
resource_tx.send(Box::new(listener)).unwrap();
while let Ok(runnable) = main_rx.recv() {
runnable.handler();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment