Created
May 8, 2018 14:41
-
-
Save segfo/5f0692a37d7e798660875e82b17e9934 to your computer and use it in GitHub Desktop.
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
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