Created
March 3, 2015 01:57
-
-
Save jdm/6d0eda6dbdcbbb13c799 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(core, std_misc)] | |
#![allow(raw_pointer_derive)] | |
use std::mem; | |
use std::sync::{Arc, Mutex}; | |
use std::sync::mpsc::{Sender, Receiver, channel}; | |
use std::thread::Thread; | |
use std::thunk::Thunk; | |
trait AsyncResponseTarget { | |
fn invoke_with_listener<'a>(&self, f: Thunk<(&'a (AsyncResponseListener+'a),)>); | |
} | |
trait AsyncResponseListener { | |
fn foo(&self); | |
} | |
fn resource_task(rx: Receiver<Box<AsyncResponseTarget+Send>>) { | |
let target = rx.recv().unwrap(); | |
target.invoke_with_listener(Thunk::with_arg(move |(listener,): (&AsyncResponseListener,)| { | |
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<'a>(&self, f: Thunk<(&'a (AsyncResponseListener+'a),)>) { | |
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<'a> { | |
foo: Arc<Mutex<FooContext>>, | |
f: Thunk<(&'a (AsyncResponseListener+'a),)>, | |
} | |
impl<'a> Runnable for MainThreadInvoke<'a> { | |
fn handler(self: Box<Self>) { | |
let this = *self; | |
let foo = this.foo.lock().unwrap(); | |
this.f.invoke((&*foo,)); | |
} | |
} | |
struct MainThreadFoo { | |
n: u64, | |
_n2: u64, | |
} | |
fn main() { | |
let (resource_tx, resource_rx) = channel(); | |
let (main_tx, main_rx) = channel(); | |
Thread::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(); | |
} | |
} |
Author
jdm
commented
Mar 3, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment