-
-
Save nlinker/995f762419a0589939b81efc3721cb8d to your computer and use it in GitHub Desktop.
Rust code shared from the playground
This file contains hidden or 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(optin_builtin_traits)] | |
mod userspace { | |
use unit::Unit; | |
use session::{Ai, DataTrait, Session}; | |
#[derive(Debug)] | |
struct MyAi(); | |
#[derive(Debug)] | |
struct MyData<'a>{ | |
units: Vec<&'a mut Unit> | |
} | |
impl<'a> Default for MyData<'a>{ | |
fn default() -> MyData<'a>{ | |
MyData{units: vec![]} | |
} | |
} | |
impl<'a> DataTrait<'a> for MyData<'a> {} | |
impl<'a> Ai<'a> for MyAi where MyData<'a>: 'static + ::std::fmt::Debug { | |
type Data = MyData<'a>; | |
fn on_unit_show<'b>(&mut self, data: &'b mut Self::Data, unit: &'a mut Unit) { | |
println!("On unit show. Unit: {:?}", unit); | |
//::std::thread::spawn(move || {let _ = unit;}); //`unit::Unit` cannot be sent between threads safely | |
data.units.push(unit); | |
} | |
fn on_frame<'b>(&mut self, data: &'b mut Self::Data) { | |
println!("On frame. Data: {:?}", data); | |
} | |
fn on_start<'b>(&mut self, _data: &'b mut Self::Data) { | |
println!("On start"); | |
} | |
fn on_end<'b>(&mut self, _data: &'b mut Self::Data) { | |
println!("On end"); | |
} | |
} | |
pub fn start() { | |
Session::new(MyAi()).setup(); | |
} | |
} | |
use unit::Unit; | |
use session::handler::Handler; | |
extern fn raw_unit_show(unit: *mut Unit) { | |
Handler::with(|callbacks| callbacks.on_unit_show(unit)); | |
} | |
extern fn raw_on_frame() { | |
Handler::with(|callbacks| callbacks.on_frame()); | |
} | |
extern fn raw_on_start() { | |
Handler::with(|callbacks| callbacks.on_start()); | |
} | |
extern fn raw_on_end() { | |
Handler::with(|callbacks| callbacks.on_end()); | |
} | |
fn main () { | |
userspace::start(); | |
//raw_on_frame(); //thread 'main' panicked at 'Data dropped', /checkout/src/libcore/option.rs:823 | |
raw_on_start(); //On start | |
let u = Box::new(Unit(333)); | |
raw_unit_show(Box::into_raw(u)); //On unit show. Unit: Unit(333) | |
raw_on_frame(); //On frame. Data: MyData { units: [Unit(333)] } | |
raw_on_end(); //On end | |
//raw_on_frame(); //thread 'main' panicked at 'Data dropped', /checkout/src/libcore/option.rs:794 | |
raw_on_start(); //On start | |
raw_on_frame(); //On frame. Data: MyData { units: [] } | |
} | |
//where D: ::std::fmt::Debug | |
mod unit { | |
#[derive(Debug)] | |
pub struct Unit(pub i32); | |
//use std::marker::Sync; | |
//use std::marker::Send; | |
impl !Sync for Unit{} | |
impl !Send for Unit{} | |
} | |
mod session { | |
use unit::Unit; | |
use std::marker::PhantomData; | |
pub trait DataTrait<'a>: Default { | |
} | |
#[derive(Debug)] | |
pub struct Session<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> { | |
data: Option<Box<D>>, | |
ai: A, | |
_p: PhantomData<&'a ()> | |
} | |
#[allow(unused_variables)] | |
pub trait Ai<'a>{ | |
type Data: 'static + DataTrait<'a>; | |
fn on_unit_show<'b>(&mut self, data: &'b mut Self::Data, unit: &'a mut Unit) {} | |
fn on_frame<'b>(&mut self, data: &'b mut Self::Data) {} | |
fn on_start<'b>(&mut self, data: &'b mut Self::Data) {} | |
fn on_end<'b>(&mut self, data: &'b mut Self::Data) {} | |
} | |
pub trait Callbacks { | |
fn on_unit_show(&mut self, unit: *mut Unit); | |
fn on_frame(&mut self); | |
fn on_start(&mut self); | |
fn on_end(&mut self); | |
} | |
pub mod handler { | |
use super::Callbacks; | |
use std::cell::Cell; | |
thread_local! { | |
static HANDLER: Handler = Handler::new(); | |
} | |
pub struct Handler { | |
inner: Cell<Option<Box<Callbacks>>> | |
} | |
impl Handler { | |
fn new() -> Self { | |
Handler { | |
inner: Cell::new(None) | |
} | |
} | |
pub fn set<T: 'static + Callbacks>(callbacks: Box<T>) { | |
HANDLER.with(|handler| { | |
handler.inner.set(Some(callbacks)); | |
}); | |
} | |
pub fn _clear(&self) { | |
HANDLER.with(|handler| { | |
handler.inner.set(None); | |
}); | |
} | |
pub fn with<F:FnOnce(&mut Callbacks)>(f: F) { | |
HANDLER.with(|handler| { | |
let mut callbacks = handler.inner.take().expect("Callbacks didn't set"); | |
f(&mut *callbacks); | |
handler.inner.set(Some(callbacks)) | |
}); | |
} | |
} | |
} | |
impl<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> Callbacks for Session<'a, D, A> where Session<'a, D, A>: 'static { | |
fn on_unit_show(&mut self, unit: *mut Unit) { | |
let unit: &'a mut Unit = unsafe{&mut *unit}; | |
self.with_components(move |data, ai| ai.on_unit_show(data, unit)); | |
} | |
fn on_frame(&mut self) { | |
self.with_components(move |data, ai| ai.on_frame(data)); | |
} | |
fn on_start(&mut self) { | |
self.data = Some(Box::new(<D as Default>::default())); | |
self.with_components(move |data, ai| ai.on_start(data)); | |
} | |
fn on_end(&mut self) { | |
self.with_components(move |data, ai| ai.on_end(data)); | |
self.data = None; | |
} | |
} | |
impl<'a, D: 'static + DataTrait<'a>, A:Ai<'a, Data=D>> Session<'a, D, A> where Session<'a, D, A>: 'static { | |
pub fn new(ai: A) -> Self { | |
Session{data: None, ai, _p: PhantomData} | |
} | |
fn components(&mut self) -> (&mut D, &mut A) { | |
( | |
&mut *self.data.as_mut().expect("Data dropped"), | |
&mut self.ai | |
) | |
} | |
fn with_components<F:FnOnce(&mut D, &mut A)>(&mut self, f: F) { | |
let (data, ai) = self.components(); | |
f(data, ai); | |
} | |
pub fn setup(self) { | |
handler::Handler::set(Box::new(self)); | |
} | |
//fn raw_unit_show(unit: *mut Unit) { | |
//let unit: &mut Unit = unsafe{&mut *unit}; | |
//self.ai.unit_show(&mut game, unit); | |
//}).unwrap(); | |
//} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The solution by @qthree for the problem of managing Game lifetime