Skip to content

Commit 3ef53b2

Browse files
committed
Restructure window thread to use futures
1 parent b1d6f9c commit 3ef53b2

File tree

1 file changed

+78
-56
lines changed

1 file changed

+78
-56
lines changed

src/main.rs

Lines changed: 78 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
#![feature(fnbox)]
23
#![feature(const_fn)]
34
#![feature(libc)]
45
#![feature(trace_macros)]
@@ -19,6 +20,7 @@ use rjs::jslib::eventloop;
1920
use tokio_core::reactor::Timeout;
2021
use tokio_core::reactor::Core;
2122
use futures::future::Future;
23+
use futures::IntoFuture;
2224

2325
use std::os::raw::c_void;
2426
use mozjs::jsapi;
@@ -64,6 +66,7 @@ use mozjs::jsapi::JSPropertySpec;
6466
use mozjs::jsapi::{JS_GetContext, JS_SetPrivate, JS_GetPrivate, JS_InitStandardClasses};
6567
use futures::sync::mpsc::{unbounded, UnboundedSender, UnboundedReceiver};
6668
use futures::Stream;
69+
use tokio_core::reactor::Interval;
6770

6871
use glutin::GlContext;
6972

@@ -83,6 +86,7 @@ use std::ffi::CString;
8386
//use std::fmt::Display;
8487
use std::sync::{Once, ONCE_INIT};
8588
use std::thread;
89+
use std::boxed::FnBox;
8690

8791

8892

@@ -302,6 +306,15 @@ struct Window {
302306
send_msg: UnboundedSender<WindowMsg>,
303307
}
304308

309+
macro_rules! window_get_private {
310+
($this:ident) => {
311+
unsafe {
312+
let win = JS_GetPrivate($this.to_object()) as *mut Window;
313+
&*win
314+
}
315+
}
316+
}
317+
305318
js_class!{ Window
306319
[JSCLASS_HAS_PRIVATE]
307320

@@ -352,25 +365,17 @@ js_class!{ Window
352365
}
353366

354367
fn ping(this: @this) -> JSRet<()> {
355-
unsafe {
356-
let win = JS_GetPrivate(this.to_object()) as *mut Window;
368+
let win = window_get_private!(this);
357369

358-
(*win).send_msg.unbounded_send(
359-
WindowMsg::Ping
360-
);
361-
}
370+
win.send_msg.unbounded_send(WindowMsg::Ping);
362371

363372
Ok(())
364373
}
365374

366375
fn close(this: @this) -> JSRet<()> {
367-
unsafe {
368-
let win = JS_GetPrivate(this.to_object()) as *mut Window;
376+
let win = window_get_private!(this);
369377

370-
(*win).send_msg.unbounded_send(
371-
WindowMsg::Close
372-
);
373-
}
378+
win.send_msg.unbounded_send(WindowMsg::Close);
374379

375380
Ok(())
376381
}
@@ -394,12 +399,13 @@ js_class!{ Window
394399
}
395400
}
396401

397-
#[derive(Debug)]
398402
enum WindowMsg {
403+
Do(Box<FnBox(&glutin::GlWindow) + Send>),
399404
Ping,
400405
Close,
401406
}
402407

408+
403409
#[derive(Debug)]
404410
enum WindowEvent {
405411
Closed,
@@ -408,6 +414,7 @@ enum WindowEvent {
408414
use std::cell::RefCell;
409415
use std::rc::Rc;
410416

417+
411418
fn window_thread(recv_msg: UnboundedReceiver<WindowMsg>, send_events: UnboundedSender<WindowEvent>) {
412419
let mut core = Core::new().unwrap();
413420

@@ -425,65 +432,80 @@ fn window_thread(recv_msg: UnboundedReceiver<WindowMsg>, send_events: UnboundedS
425432
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
426433
}
427434

435+
let (stop_send, stop_recv) = futures::sync::oneshot::channel();
436+
let stop_recv = stop_recv.map_err(|err| ());
437+
428438
struct WindowStuff {
429439
gl_window: glutin::GlWindow,
430-
run: bool,
440+
stop: Option<futures::sync::oneshot::Sender<()>>,
441+
}
442+
443+
impl WindowStuff {
444+
fn stop(&mut self) {
445+
let stop = self.stop.take();
446+
stop.map(|stop| stop.send(()));
447+
}
431448
}
432449

433450
// This could just be a let mut if tokio used lifetimes
434451
let stuff = Rc::new(RefCell::new(WindowStuff {
435452
gl_window: gl_window,
436-
run: true,
453+
stop: Some(stop_send),
437454
}));
438455

439-
{
440-
let stuff = stuff.clone(); // grrr. Why no clone closures?
441-
core.handle().spawn(
442-
recv_msg.for_each(move |msg| -> Result<(), ()> {
443-
println!("Window msg: {:?}", &msg);
456+
457+
let recv_msgs = {
458+
let stuff = stuff.clone();
459+
recv_msg.for_each(move |msg| -> Result<(), ()> {
460+
let mut stuff = stuff.borrow_mut();
461+
let stuff = &mut *stuff;
462+
match msg {
463+
WindowMsg::Do(func) => { func.call_box((&stuff.gl_window,)); },
464+
WindowMsg::Ping => { println!("ping"); },
465+
WindowMsg::Close => {
466+
println!("close");
467+
stuff.stop();
468+
stuff.gl_window.hide();
469+
},
470+
}
471+
472+
Ok(())
473+
}).map_err(|_| ())
474+
};
475+
476+
let handle_window_events =
477+
Interval::new(Duration::from_millis(16), &core.handle()).unwrap()
478+
.map_err(|err| { println!("Interval err: {}", err); () })
479+
.for_each(move |()| -> Result<(), ()> {
444480
let mut stuff = stuff.borrow_mut();
445481
let stuff = &mut *stuff;
446-
match msg {
447-
WindowMsg::Ping => { println!("ping"); },
448-
WindowMsg::Close => {
449-
stuff.run = false;
450-
stuff.gl_window.hide();
451-
},
482+
483+
unsafe {
484+
gl::Clear(gl::COLOR_BUFFER_BIT);
452485
}
486+
stuff.gl_window.swap_buffers().unwrap();
487+
488+
events_loop.poll_events(|event| {
489+
println!("glutin event: {:?}", event);
490+
match event {
491+
glutin::Event::WindowEvent { event, .. } => match event {
492+
glutin::WindowEvent::Closed => {
493+
stuff.stop();
494+
stuff.gl_window.hide();
495+
send_events.unbounded_send(WindowEvent::Closed);
496+
},
497+
glutin::WindowEvent::Resized(w, h) => stuff.gl_window.resize(w, h),
498+
_ => ()
499+
},
500+
_ => ()
501+
}
502+
});
453503

454504
Ok(())
455505
})
456-
);
457-
}
458-
459-
while (*stuff.borrow()).run {
460-
core.turn(Some(Duration::from_millis(16)));
461-
462-
let mut stuff = stuff.borrow_mut();
463-
let stuff = &mut *stuff;
506+
;
464507

465-
unsafe {
466-
gl::Clear(gl::COLOR_BUFFER_BIT);
467-
}
468-
stuff.gl_window.swap_buffers().unwrap();
469-
470-
events_loop.poll_events(|event| {
471-
println!("glutin event: {:?}", event);
472-
match event {
473-
glutin::Event::WindowEvent { event, .. } => match event {
474-
glutin::WindowEvent::Closed => {
475-
stuff.run = false;
476-
stuff.gl_window.hide();
477-
send_events.unbounded_send(WindowEvent::Closed);
478-
},
479-
glutin::WindowEvent::Resized(w, h) => stuff.gl_window.resize(w, h),
480-
_ => ()
481-
},
482-
_ => ()
483-
}
484-
})
485-
}
508+
core.run(stop_recv.select(handle_window_events).then(|_| -> Result<(),()> { Ok(()) }).select(recv_msgs));
486509

487510
println!("window_thread exiting");
488-
489511
}

0 commit comments

Comments
 (0)