Right now I have a background thread that I'm communicating with using a channel. The details aren't important but I have an enum Message
with a variant Variant(Data, Sender<Response>)
, so that in the background thread I can do:
loop {
match message_rx.recv() {
Ok(Message::Variant(data, sender)) => {
let result = do_something(data);
sender.send(result);
}
}
}
And in the foreground thread(s),
let (response_rx, response_tx) = flume::bounded(1);
message_tx.send(Message::Variant(data, response_tx));
let response = response_rx.recv();
This solution is not concurrent (nor is concurrency a particular goal here) but is it in fact a solution? I was inspired by the Erlang pattern where a process sends its pid with a message so it can receive a response.
CodePudding user response:
It is indeed a pattern, as in your example, embedding a reply communication channel within the message is a good way of doing it,
You can find different utilities for it, for example in an asynchronous environment using tokio, you could use oneshot
, which is a channel that ensures a single message, from the example:
use tokio::sync::oneshot;
#[tokio::main]
async fn main() {
let (tx, rx) = oneshot::channel();
tokio::spawn(async move {
if let Err(_) = tx.send(3) {
println!("the receiver dropped");
}
});
match rx.await {
Ok(v) => println!("got = {:?}", v),
Err(_) => println!("the sender dropped"),
}
}