concepts: Add alternative Post implementation with states as types
[learn-rust.git] / concepts / src / main.rs
index 06d122b9c4c727f399d8273312ffcfb2a95088fd..4b6df6447be9930e5773202f24601cd817722eb8 100644 (file)
@@ -4,6 +4,7 @@ mod lib;
 use std::collections::HashMap;
 use std::io::{prelude::*, ErrorKind};
 use std::fs::{self, File};
+use std::{thread, time, sync};
 
 use lib::*;
 use word_utils::{first_word, second_word};
@@ -189,6 +190,99 @@ fn test_iterators() {
     }
 }
 
+fn test_threads() {
+    let t1 = thread::spawn(|| {
+        for i in 0..10 {
+            println!("hello #{} from thread", i);
+            thread::sleep(time::Duration::from_millis(1));
+        }
+    });
+
+    for i in 1..5 {
+        println!("hello #{} from main", i);
+        thread::sleep(time::Duration::from_millis(1));
+    }
+
+    t1.join().unwrap();
+
+    // message passing
+    let (tx1, rx) = sync::mpsc::channel();
+    let tx2 = tx1.clone();
+
+    let sender1 = thread::spawn(move || {
+        for s in ["hey", "from", "sender", "one"] {
+            tx1.send(s).expect("failed to send");
+            thread::sleep(time::Duration::from_millis(100));
+        }
+    });
+
+    let sender2 = thread::spawn(move || {
+        for s in ["Servus", "von", "Produzent", "zwei"] {
+            tx2.send(s).expect("failed to send");
+            thread::sleep(time::Duration::from_millis(100));
+        }
+    });
+
+    for received in rx {
+        println!("received {} from mpsc", received);
+    }
+
+    sender1.join().unwrap();
+    sender2.join().unwrap();
+
+    // shared state
+    let counter = sync::Arc::new(sync::Mutex::new(0));
+    let mut threads = vec![];
+    for _ in 0..10 {
+        let tc = sync::Arc::clone(&counter);
+        threads.push(thread::spawn(move || {
+            *tc.lock().unwrap() += 1;
+        }));
+    }
+
+    for t in threads {
+        t.join().unwrap();
+    }
+
+    println!("counter: {}", *counter.lock().unwrap());
+}
+
+fn test_dyn_traits() {
+    let text = "I ate a salad for lunch today";
+    let mut post = Post::new();
+    post.add_text(text);
+    assert_eq!("", post.content());
+
+    post.request_review();
+    assert_eq!("", post.content());
+
+    post.reject();
+    assert_eq!("", post.content());
+
+    post.request_review();
+    assert_eq!("", post.content());
+
+    post.approve();  // first
+    assert_eq!("", post.content());
+
+    post.approve();  // second
+    assert_eq!(text, post.content());
+
+    post.reject();  // no-op
+    assert_eq!(text, post.content());
+}
+
+fn test_state_types() {
+    let mut post = TPost::new();
+    post.add_text("I ate a salad for lunch");
+    let post = post.request_review();
+    let mut post = post.reject();
+    post.add_text(" today");
+    let post = post.request_review();
+    let post = post.approve();
+    assert_eq!(post.content(), "I ate a salad for lunch today");
+}
+
 fn main() {
     test_strings();
     test_vectors();
@@ -197,4 +291,7 @@ fn main() {
     test_generics();
     test_closures();
     test_iterators();
+    test_threads();
+    test_dyn_traits();
+    test_state_types();
 }