diff --git a/presentation/codes/concurrent/src/main.rs b/presentation/codes/concurrent/src/main.rs index 611c6e920954244e7ff297d51ac6a9a5387b127b..2e4fa8feafeebb6279cc3ebe825aaf612551dc3d 100644 --- a/presentation/codes/concurrent/src/main.rs +++ b/presentation/codes/concurrent/src/main.rs @@ -1,17 +1,92 @@ use std::thread; +use std::sync::Arc; -fn main() { +fn move_borrow() { + // // cannot borrow v: + // // comportement possible: le programme a fini avant qu'on ait pu faire un push par exemple. + // let mut v = Vec::new(); + // let loc = thread::spawn(|| { + // v.push(1); + // }); + // v.push(4); + // println!("{:?}", loc.join().unwrap()); - let loc = thread::spawn( || { - "world" - }); - println!("Hello {}!", loc.join().unwrap()); + // // v moved in thread, cannot be used elsewhere + // let mut v = Vec::new(); + // let loc = thread::spawn(move || { + // v.push(1); + // v + // }); + // v.push(4); + // println!("{:?}", loc.join().unwrap()); + // here it works let mut v = Vec::new(); let loc = thread::spawn(move || { v.push(1); v }); println!("{:?}", loc.join().unwrap()); +} + +fn share_with_rc() { + // let v = Rc::new(vec![1,2,3,4]); // reference counted + // let v_cloned = v.clone(); // create a new reference + // + // // rc cannot be sent between threads safely. + // thread::spawn(move || { + // println!("{:?}", v); + // }); + + // // Arc can be sent between threads safely. + // let v = Arc::new(vec![1,2,3,4]); // reference counted + // let v_cloned = v.clone(); // create a new reference + // thread::spawn(move || { + // println!("{:?}", v); + // }); + + // println!("{:?}", v_cloned); + + // Arc can be sent between threads safely. + let v = Arc::new(vec![1,2,3,4]); // reference counted + let v_cloned = v.clone(); // create a new reference + thread::spawn(move || { + println!("{:?}", v); + }); + + println!("{:?}", v_cloned); + +} + +fn spawn_unordered_not_finishing() { + for i in 0..10 { + let loc = thread::spawn(move || { + println!("Hello from child thread {}!", i); + }); + } + + for i in 0..10 { + println!("Hello {} from main thread!", i); + } +} + +fn spawn_unordered_join() { + let mut handles = Vec::new(); + for i in 0..10 { + handles.push(thread::spawn(move || { + println!("Hello from child thread {}!", i); + })); + } + + for h in handles { + h.join(); + } +} + +fn main() { + spawn_unordered_not_finishing() + + spawn_unordered_join(); + // share_with_rc(); } diff --git a/presentation/intro.md b/presentation/intro.md index a80fa75108bbd40751790e1e869d5ae05867dde4..0965732612d03e3cb99b6e2b26d22d4ca2e45cca 100644 --- a/presentation/intro.md +++ b/presentation/intro.md @@ -393,12 +393,36 @@ Les "data-race" surviennent quand: . . . -Le partage des données et la mutation est incompatible en Rust. +Le partage des données et la mutation est incompatible en Rust: leur absence est garantie à la compilation -## Rust prévient à la compilation +# La concurrence en pratique -- Les accès concurrents. -- +## thread::spawn .join() + +La sytaxe pour créer un `thread` et le synchroniser +avec le thread principal est `thread::spawn` et `.join()` + +<pre><code data-trim="hljs rust" class="lang-rust"> +fn main() { + let v = vec![1,2,3]; + + let handle = thread::spawn(move || { // si on enlève move... + println!("{:?}", v); // ça ne compile plus + }); + + handle.join(); +} +</code></pre> + +. . . + +Sans le `move` on peut avoir des **accès concurrents** aux données. + +## std::rc::Rc + + + +## std::sync::Arc # And many more