Skip to content

Instantly share code, notes, and snippets.

@jdm
Created March 3, 2015 01:57
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 jdm/6d0eda6dbdcbbb13c799 to your computer and use it in GitHub Desktop.
Save jdm/6d0eda6dbdcbbb13c799 to your computer and use it in GitHub Desktop.
#![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();
}
}
@jdm
Copy link
Author

jdm commented Mar 3, 2015

/Users/jdm/src/thunk.rs:69:19: 69:27 error: `this.foo` does not live long enough
/Users/jdm/src/thunk.rs:69         let foo = this.foo.lock().unwrap();
                                             ^~~~~~~~
/Users/jdm/src/thunk.rs:67:33: 71:6 note: reference must be valid for the lifetime 'a as defined on the block at 67:32...
/Users/jdm/src/thunk.rs:67     fn handler(self: Box<Self>) {
/Users/jdm/src/thunk.rs:68         let this = *self;
/Users/jdm/src/thunk.rs:69         let foo = this.foo.lock().unwrap();
/Users/jdm/src/thunk.rs:70         this.f.invoke((&*foo,));
/Users/jdm/src/thunk.rs:71     }
/Users/jdm/src/thunk.rs:68:25: 71:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 68:24
/Users/jdm/src/thunk.rs:68         let this = *self;
/Users/jdm/src/thunk.rs:69         let foo = this.foo.lock().unwrap();
/Users/jdm/src/thunk.rs:70         this.f.invoke((&*foo,));
/Users/jdm/src/thunk.rs:71     }
/Users/jdm/src/thunk.rs:70:26: 70:29 error: `foo` does not live long enough
/Users/jdm/src/thunk.rs:70         this.f.invoke((&*foo,));
                                                    ^~~
/Users/jdm/src/thunk.rs:67:33: 71:6 note: reference must be valid for the lifetime 'a as defined on the block at 67:32...
/Users/jdm/src/thunk.rs:67     fn handler(self: Box<Self>) {
/Users/jdm/src/thunk.rs:68         let this = *self;
/Users/jdm/src/thunk.rs:69         let foo = this.foo.lock().unwrap();
/Users/jdm/src/thunk.rs:70         this.f.invoke((&*foo,));
/Users/jdm/src/thunk.rs:71     }
/Users/jdm/src/thunk.rs:69:43: 71:6 note: ...but borrowed value is only valid for the block suffix following statement 1 at 69:42
/Users/jdm/src/thunk.rs:69         let foo = this.foo.lock().unwrap();
/Users/jdm/src/thunk.rs:70         this.f.invoke((&*foo,));
/Users/jdm/src/thunk.rs:71     }
error: aborting due to 2 previous errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment