Need help in solving the error in watch channel tokio

49 Views Asked by At
use std::mem::{self, ManuallyDrop};

/// single producer multi consumer

#[tokio::main]
async fn main() {
    use tokio::sync::watch;
    use tokio::time::{Duration, sleep};

    let (tx, _rx) = watch::channel("hello");
    let mut rx2 = tx.subscribe();
    tokio::spawn(async move {
        loop {
            let res = rx2.has_changed();
            if res.is_err() {
                break;
            }
            if !res.ok().unwrap_or_else(|| true ) {
                continue;
            }
            println!("{}! ", *rx2.borrow_and_update());
        }
    });

    sleep(Duration::from_millis(1000)).await;
    for i in 0..10 {
        let val = format!("World {}!", i);
        tx.send(val.as_str()).unwrap();
    }
    sleep(Duration::from_millis(1000)).await;
}

This code fails with error:

error[E0597]: `val` does not live long enough
  --> src/main.rs:28:17
   |
27 |         let val = format!("World {}!", i);
   |             --- binding `val` declared here
28 |         tx.send(val.as_str()).unwrap();
   |                 ^^^---------
   |                 |
   |                 borrowed value does not live long enough
   |                 argument requires that `val` is borrowed for `'static`
29 |     }
   |     - `val` dropped here while still borrowed

Can anyone help me send the message to all the consumers in the correct way?

1

There are 1 best solutions below

2
cdhowie On

Because of this line, the element type of the channel is inferred to be &str:

let (tx, _rx) = watch::channel("hello");

Then, you send val.as_str() which returns a &str that borrows from val, but val is going to be destroyed when the loop iteration ends.

Just send owned values (String) instead of borrowed ones. You can do this by sending val instead of val.as_str(). You will also have to send "hello".to_owned() instead of "hello" to make the types match.