Poperton
Poperton

Reputation: 1766

Wake another thread periodically with Rust

Condvar in Rust is good for waking another thread, but in this case below, I don't really need the true, I just want to wake the other thread periodically

use std::sync::{Arc, Mutex, Condvar};
use std::thread;
fn main() {
    let pair = Arc::new((Mutex::new(false), Condvar::new()));
    let pair2 = Arc::clone(&pair);
    
    // Inside of our lock, spawn a new thread, and then wait for it to start.
    thread::spawn(move|| {
        let (lock, cvar) = &*pair2;
        let mut started = lock.lock().unwrap();
        // We notify the condvar that the value has changed.
        loop{
            *started = true;
            cvar.notify_one();
            std::thread::sleep(std::time::Duration::from_millis(20));
        }
    });
    
    // Wait for the thread to start up.
    let (lock, cvar) = &*pair;
    let mut started = lock.lock().unwrap();
    loop {
        started = cvar.wait(started).unwrap();
        println!("done");
    }
    println!("end");
}

Also, this example does not even work, I don't know why. It should wake the main thread every 20 ms.

Upvotes: 0

Views: 758

Answers (1)

Caesar
Caesar

Reputation: 8544

The reason this doesn't work is that you're holding the mutex while you sleep. The main thread is only woken up after it has been hit with notify_one and its mutex is lockable. But the spawned thread holds the mutex locked forever.

Playground

In fact, you don't need the lock at all in your spawned thread and you could make it contain no data by constructing it as Mutex::new(()). However, if you do that, it is possible that your main thread hasn't finished one loop by the time the spawned thread finishes its sleep. The mutex ensures that when you call notify_one, the main thread is definitely waiting to be notified. If you want that behavior or not is up to you. With locking the mutex in the spawned thread, the main thread is woken up immediately if its previous loop took longer than one tick. Without the locking, wake-ups may be skipped and the next wake-up is aligned to the next tick.

But really, do what's in the answers @Finomnis suggested and use channels.

Upvotes: 0

Related Questions