Skip to content

Instantly share code, notes, and snippets.

@segfo
Created May 8, 2018 14:41
Show Gist options
  • Save segfo/5f0692a37d7e798660875e82b17e9934 to your computer and use it in GitHub Desktop.
Save segfo/5f0692a37d7e798660875e82b17e9934 to your computer and use it in GitHub Desktop.
use std::thread;
use std::time::Duration;
use std::sync::{Arc,Mutex};
use std::ptr::NonNull;
// いんなー
// 32ビット整数値と、外部の配列へのポインタ(C-FFIとかでよくやるやつ)
struct Inner{
num:u32,
u8ptr:SafeRawU8Ptr
}
// あうたー
struct Outer{
value:Inner
}
// ポインタはNonNullであることを保証しなければならないので、ラッピングする
struct SafeRawU8Ptr(NonNull<u8>);
// スレッド間で共有可能であることをSend Traitを実装することで保証する
unsafe impl std::marker::Send for SafeRawU8Ptr { }
fn main() {
let mut th_list=Vec::new();
let hoge = 0;
let mut data = 0u8;
let ans=Arc::new(Mutex::new(
Outer{
value:Inner{
num:0,
u8ptr:SafeRawU8Ptr(NonNull::new(&mut data).unwrap())
}
}
));
// 10スレッドを生成
for i in 0..10{
let ans=ans.clone();
let th = thread::spawn(move || {
// 競合が発生しない重い処理 の代わりに2秒スリープ
thread::sleep(Duration::from_secs(2));
// 競合が発生する軽めの処理(足し算)
// 構造体をロックする
let mut ans=ans.lock().unwrap();
// 普通の32ビット整数値に足し算する
(*ans).value.num +=1;
// ポインタ経由で足し算する
unsafe{*(*ans).value.u8ptr.0.as_ptr()+=2;}
println!("thread id {} destroyed.",i);
});
th_list.push(th);
}
//すべてのスレッドが終わるまで待つ
for th in th_list{
let _ = th.join();
}
// 構造体に存在する32ビット整数値の値
println!("num:{}",(*ans.lock().unwrap()).value.num);
// ポインタ経由で更新された変数の値
println!("data(via ptr): {}",data);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment