空のメモリと交換することでクロージャの所有権をthread::spawn
へ渡して動作させることが出来るようにする。
元の変数は空の状態になる。
ちなみにクロージャの定義の外で拘束した値は、'static
である必要があるmove
をつけることで、所有権を移転出来る。
use std::thread;
use std::time::Duration;
//
// Option を使った方法
//
mod func {
use std::thread;
// 型定義
// Sendを明示的に指定する。
pub type FuncType = Option<Box<dyn Fn() -> Result<(), String> + Send>>;
pub struct Func {
pub name: String,
pub funcs: FuncType,
}
impl Func {
pub fn exec(&mut self) {
println!("func function start.");
// 空の変数を作る。
let mut funcs: FuncType = None;
// ここで後の処理で使えるようにメモリを交換
std::mem::swap(&mut self.funcs, &mut funcs);
thread::spawn(|| {
match funcs {
Some(f) => {
// Fnなので複数回使える。
(f)();
(f)();
println!("func closure end.");
}
None => {}
}
});
println!("func function end.");
}
}
}
fn func_main() {
let a: String = "closure out side Variable a".to_string();
let b: &str = "closure out side Variable b";
let c: String = "closure out side Variable c".to_string();
let func: func::FuncType = Some(Box::new(move || { // moveをつけることでaとcの所有権を移転
println!("func start");
println!(" --> {}", a); // 所有権が移転された。
println!(" --> {}", b); // 参照のみなので移転しない。
println!(" --> {}", &c); // 参照を指してもエラー。
thread::sleep(Duration::from_millis(1000));
println!("func end");
Ok(())
}));
// println!(" > {}", a); // これはエラーになる。
println!(" > {}", b); // これは問題ない。
// println!(" --> {}", &c); // これはエラーになる
let mut tmp = func::Func { name: "test".to_string(), funcs: func };
tmp.exec();
}
//
// Vecを使った方法
//
mod funcs {
use std::thread;
pub type FuncsType = Vec<Box<dyn Fn() -> Result<(), String> + Send>>;
pub struct Funcs {
pub name: String,
pub funcs: FuncsType,
}
impl Funcs {
pub fn exec(&mut self) {
println!("funcs function start.");
// 空のベクトルを作る。
let mut funcs: FuncsType = vec![];
// ここでメモリを交換
std::mem::swap(&mut self.funcs, &mut funcs);
thread::spawn(|| {
for f in funcs {
(f)();
(f)();
println!("funcs closure once end.");
}
println!("funcs closure end.");
});
println!("funcs function end.");
println!("funcs function length is {}.",self.funcs.len() );
}
}
}
fn funcs_main() {
let func: funcs::FuncsType = vec![Box::new(|| {
println!("funcs start");
thread::sleep(Duration::from_millis(1000));
println!("funcs end");
Ok(())
})];
let mut tmp = funcs::Funcs { name: "test".to_string(), funcs: func };
tmp.exec();
}
fn main() {
func_main();
funcs_main();
thread::sleep(Duration::from_millis(5000));
}