Revisited: How to pass immutable parameters to a thread? (about lifetimes) - multithreading

This my question was answered.
But when I modified the code a little, it does not work again with a compilation error similar to the error in the previous question. What is my error now?
use std::thread;
#[derive(Clone)]
struct Params<'a> {
x: &'a i32,
}
struct State<'a> {
params: &'a Params<'a>,
y: i32,
}
impl<'a> State<'a> {
fn new(params: &'a Params<'a>) -> Self {
State {
params,
y: 0,
}
}
fn start(&mut self) -> thread::JoinHandle<()> {
let params = self.params.clone();
thread::spawn(move || { params; /* ... */ })
}
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:21:34
|
21 | let params = self.params.clone();
| ^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 13:6...
--> src/lib.rs:13:6
|
13 | impl<'a> State<'a> {
| ^^
note: ...so that the types are compatible
--> src/lib.rs:21:34
|
21 | let params = self.params.clone();
| ^^^^^
= note: expected `&Params<'_>`
found `&Params<'a>`
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure#src/lib.rs:22:23: 22:52 params:Params<'_>]` will meet its required lifetime bounds
--> src/lib.rs:22:9
|
22 | thread::spawn(move || { params; /* ... */ })
| ^^^^^^^^^^^^^

Instead of using references I would suggest using a reference counted type (Arc), that way you do not need to worry about lifetimes.
use std::thread;
use std::sync::Arc;
#[derive(Clone)]
struct Params {
x: i32,
}
struct State {
params: Arc<Params>,
y: i32,
}
impl State {
fn new(params: &Arc<Params>) -> Self {
State {
params: params.clone(),
y: 0,
}
}
fn start(&self) -> thread::JoinHandle<()> {
let params = self.params.clone();
thread::spawn(move || { params; /* ... */ })
}
}
If you want to mutate the state later on, you would need to wrap the Params type in the State struct with a Mutex like Arc<Mutex<Params>>.
More on the topic:
Rc, the Reference Counted Smart Pointer
Shared-State Concurrency
Arc-Docs

Related

future created by async block is not `Send`

I do a server update in rust. it create patches between 2 binaries files, and serves static files
I try to do
let mut update_state;
if let Some(state) = update_stream.next().await {
if let Ok(state) = state {
update_state = state
} else if let Err(err) = state {
reply = BuildOutput { error: "Update failed: ".to_string() + &err.to_string() }
}
} else {
reply = BuildOutput { error: "Unreacheable".to_string() }
}
let state = update_state.borrow();
let progress = state.histogram.progress();
let res = update_stream.try_for_each(|_state| future::ready(Ok(()))).await;
but get
note: future is not `Send` as this value is used across an await
--> server\grpc\src\rpc.rs:260:50
|
259 | let mut update_state;
| ---------------- has type `SharedUpdateProgress` which is not `Send`
260 | if let Some(state) = update_stream.next().await {
| ^^^^^^ await occurs here, with `mut update_state` maybe used later
...
305 | }
| - `mut update_state` is later dropped here
= note: required for the cast from `impl futures::Future<Output = Result<tonic::Response<BuildOutput>, Status>>` to the object type `dyn futures::Future<Output = Result<tonic::Response<BuildOutput>, Status>> + std::marker::Send
SharedUpdateProgress:
#[derive(Clone)]
pub struct SharedUpdateProgress {
state: Rc<RefCell<UpdateProgress>>,
}
impl SharedUpdateProgress {
pub fn new(target_revision: CleanName) -> Self {
Self { state: Rc::new(RefCell::new(UpdateProgress::new(target_revision))) }
}
pub fn borrow(&self) -> Ref<'_, UpdateProgress> {
self.state.borrow()
}
pub(crate) fn borrow_mut(&self) -> RefMut<'_, UpdateProgress> {
self.state.borrow_mut()
}
}
I don't know why and don't know how to fix it
I assume a minimal reproducible example of your problem is as follows:
use std::{cell::RefCell, rc::Rc};
use tokio::time::{sleep, Duration};
#[derive(Clone)]
pub struct SharedString {
state: Rc<RefCell<String>>,
}
impl SharedString {
pub fn new(initial: &str) -> Self {
Self {
state: Rc::new(RefCell::new(initial.into())),
}
}
}
async fn run() {
let shared_string = SharedString::new("Hello,");
sleep(Duration::from_millis(1)).await;
*shared_string.state.borrow_mut() += " world!";
sleep(Duration::from_millis(1)).await;
println!("{:?}", shared_string.state.borrow());
}
#[tokio::main]
async fn main() {
tokio::task::spawn(run()).await.unwrap();
}
error: future cannot be sent between threads safely
--> src/main.rs:27:24
|
27 | tokio::task::spawn(run()).await.unwrap();
| ^^^^^ future returned by `run` is not `Send`
|
= help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `Rc<RefCell<String>>`
note: future is not `Send` as this value is used across an await
--> src/main.rs:19:36
|
18 | let shared_string = SharedString::new("Hello,");
| ------------- has type `SharedString` which is not `Send`
19 | sleep(Duration::from_millis(1)).await;
| ^^^^^^ await occurs here, with `shared_string` maybe used later
...
23 | }
| - `shared_string` is later dropped here
note: required by a bound in `tokio::spawn`
--> /home/martin/.cargo/git/checkouts/tokio-dd4afa005f1f4b79/686577b/tokio/src/task/spawn.rs:163:21
|
163 | T: Future + Send + 'static,
| ^^^^ required by this bound in `tokio::spawn`
The tokio Runtime is usually multi-threaded, meaning that at any .await point your task could get moved from one thread to another. That's why everything that is held across an .await point must be Send. Which Rc<RefCell<>> is explicitely not, because it's a single-threaded reference counter.
Solution: Replace Rc<RefCell<>> with Arc<Mutex<>>, which is the thread-safe equivalent.
use std::sync::{Arc, Mutex};
use tokio::time::{sleep, Duration};
#[derive(Clone)]
pub struct SharedString {
state: Arc<Mutex<String>>,
}
impl SharedString {
pub fn new(initial: &str) -> Self {
Self {
state: Arc::new(Mutex::new(initial.into())),
}
}
}
async fn run() {
let shared_string = SharedString::new("Hello,");
sleep(Duration::from_millis(1)).await;
*shared_string.state.lock().unwrap() += " world!";
sleep(Duration::from_millis(1)).await;
println!("{:?}", shared_string.state.lock().unwrap());
}
#[tokio::main]
async fn main() {
tokio::task::spawn(run()).await.unwrap();
}
"Hello, world!"

Rust multiple borrowing struct

I am new to Rust and trying to implement a simple TCP-Server that sends me a live image. Therefore I am using this crate https://crates.io/crates/tinybmp for the RawBmp-type. Now I am struggling a bit to understand some of Rusts functionality. Or let's say I am still trying to figure out how to accomplish this in the 'Rust way'.
pub struct TCPBasePackage {
haspayload: bool,
pkgbytes: Vec<u8>,
}
impl TCPBasePackage {
pub const CMD: i32 = 0;
pub fn new() -> TCPBasePackage {
TCPBasePackage { haspayload: false, pkgbytes: Vec::new()}
}
}
impl TCPPackage for TCPBasePackage {
fn serialize(&mut self) -> &[u8] {
self.pkgbytes.append(&mut self.get_command().to_be_bytes().to_vec());
self.pkgbytes.append(&mut [u8::from(self.haspayload)].to_vec());
self.pkgbytes.as_slice()
}
fn read_from_stream(&mut self, mut stream: &TcpStream) -> Vec<u8> {
let mut vec: Vec<u8> = Vec::new();
let mut buf_pkg: [u8; 5] = [0; 5];
stream.read_exact(&mut buf_pkg).unwrap();
vec.append(&mut buf_pkg.to_vec());
self.pkgbytes = vec.to_vec();
return self.pkgbytes.clone();
}
fn deserialize(&mut self, buff: &[u8]) -> i32 {
self.haspayload = buff[4] != 0;
return 5;
}
fn get_command(&self) -> i32 {
TCPBasePackage::CMD
}
}
pub struct MsgLiveImage<'a> {
tcppackage: TCPBasePackage,
imgbytes: Vec::<u8>,
img: RawBmp<'a>,
}
impl<'a> MsgLiveImage<'a> {
pub const CMD: i32 = 2;
pub fn new() -> MsgLiveImage<'static> {
MsgLiveImage {
tcppackage: TCPBasePackage { haspayload: false, pkgbytes: Vec::new() },
imgbytes: Vec::new(),
img: RawBmp::from_slice(&[]).unwrap()
}
}
pub fn set_image_data(&'a mut self, data: Vec::<u8>) {
self.imgbytes = data;
self.img = RawBmp::from_slice(&self.imgbytes.as_slice()).unwrap();
}
}
In some function of my application I want to do this:
fn write_response_to_stream(
mut request: &Box<dyn mytcp::TCPPackage>,
mut stream: &TcpStream,
raspicam: &Arc<Mutex<camserv::CamServ>>,
) -> Result<Box<dyn mytcp::TCPPackage>, &'static str> {
match request.get_command() {
mytcp::MsgLiveImage::CMD => {
let mut pkg = mytcp::MsgLiveImage::new();
{
{
let tmpcam = raspicam.lock().unwrap(); // lock the camera server
let tmpbuff = tmpcam.imgbuff.lock().unwrap(); // lock the buffer of last image
pkg.set_image_data((*tmpbuff).clone()); // make copy of my image and transfer ownership of that copy to the package struct
}
{
let sbuff = pkg.serialize();
stream.write(&sbuff);
}
stream.flush();
}
Ok(Box::new(pkg)) // return the response package
}
_ => Err("Unknown request package"),
}
}
But the problem is, that the compiler is complaining about multiple borrowing the pkg-variable. As well as moving the pkg out of scope (which i learned should be possible by wrapping it in a Box.
Can someone explain me why the first mutable borrow still lasts even after the method returns? How can i achieve to call multiple methods on my struct without getting these borrowing conflicts?
Errors from rustc:
error[E0499]: cannot borrow `pkg` as mutable more than once at a time
--> src/raspiserv/mod.rs:90:33
|
87 | pkg.set_image_data((*tmpbuff).clone());
| -------------------------------------- first mutable borrow occurs here
...
90 | let sbuff = pkg.serialize();
| ^^^^^^^^^^^^^^^ second mutable borrow occurs here
...
95 | Ok(Box::new(pkg))
| ----------------- returning this value requires that `pkg` is borrowed for `'static`
error[E0515]: cannot return value referencing local variable `pkg`
--> src/raspiserv/mod.rs:95:13
|
87 | pkg.set_image_data((*tmpbuff).clone());
| -------------------------------------- `pkg` is borrowed here
...
95 | Ok(Box::new(pkg))
| ^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `pkg` because it is borrowed
--> src/raspiserv/mod.rs:95:25
|
87 | pkg.set_image_data((*tmpbuff).clone());
| -------------------------------------- borrow of `pkg` occurs here
...
95 | Ok(Box::new(pkg))
| ------------^^^--
| | |
| | move out of `pkg` occurs here
| returning this value requires that `pkg` is borrowed for `'static`
The problem is with your set_image_data
pub fn set_image_data(&'a mut self, data: Vec::<u8>) {
self.imgbytes = data;
self.img = RawBmp::from_slice(&self.imgbytes.as_slice()).unwrap();
}
you borrow self for the lifetime of 'a which is as long as the RawBmp inside of it is valid.
Thus the borrow lasts as long as the struct.
What you have is a self referential struct see this question on them for suggestions how to reslove this.
You can probably just drop the img from MsgLiveImage and replace it with a method:
impl MsgLiveImage {
pub fn as_img<'a>(&'a self) -> Result<RawBmp<'a>, ParseError> {
RawBmp::from_slice(&self.imgbytes.as_slice())
}
}
Might even be able to omit the lifetimes from that.

Reference should outlive closure parameter

So I've got the following structs
struct Item;
#[derive(Default)]
struct Resource<'a> {
_marker: std::marker::PhantomData<&'a ()>,
}
impl<'a> Resource<'a> {
// Note: item has to be borrowed for 'a
fn do_nothing(&mut self, item: &'a Item) {
let _ = item;
}
}
struct Context<'a> {
resource: Resource<'a>,
}
impl<'a> Context<'a> {
fn new() -> Self {
Self { resource: Resource::default() }
}
fn do_something(&mut self, item: &'a Item) {
self.resource.do_nothing(item);
}
}
And the following function that uses those sturcts.
fn do_stuff<F>(callback: F)
where
F: FnOnce(Context),
{
let ctx = Context::new();
(callback)(ctx);
}
When I try using this in the following manner
fn main() {
let item = Item;
do_stuff(|mut ctx| {
ctx.do_something(&item);
});
}
It gives the following compiler error:
error[E0597]: `item` does not live long enough
--> src/main.rs:40:27
|
39 | do_stuff(|mut ctx| {
| --------- value captured here
40 | ctx.do_something(&item);
| ------------------^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `item` is borrowed for `'static`
41 | });
42 | }
| - `item` dropped here while still borrowed
However, with my limited understanding of rust lifetimes, I'm not sure how to fix it. Item should outlive ctx as ctx only lives as long as do_stuff(?). Is there a way to tell the compiler that item lives longer then ctx?
One thing I highly recommend when dealing with lifetimes is to attempt to desugar lifetime elision as much as possible. The issue here actually happens in your definition of do_stuff:
fn do_stuff<F>(callback: F)
where
F: FnOnce(Context),
{
let ctx = Context::new();
(callback)(ctx);
}
which desugars to:
fn do_stuff<F>(callback: F)
where
F: FnOnce(Context<'static>),
{
let ctx = Context::new();
callback(ctx);
}
That 'static is what is causing the error. If you make the function generic over lifetime 'a the error goes away:
fn do_stuff<'a, F>(callback: F)
where
F: FnOnce(Context<'a>),
{
let ctx = Context::new();
callback(ctx);
}
playground

How to solve "lifetime must be valid for the static lifetime" in calling thread methods

I am a Rust beginner and I can’t get the following code to compile. I know this problem might be not new, tried searching all over the place but couldn't find a proper answer to the below problem.
Basically i m trying to call methods from thread, and also using different structs for sending and receiving objects between the threads.
use std::{thread, time};
struct SenderStruct;
impl SenderStruct {
fn send(&self, sndr: Sender<(Option<String>)>) {
let count = 0;
loop {
sndr.send(Some(String::from("Hello"))).unwrap();
thread::sleep(time::Duration::from_millis(1000));
count = count + 1;
if count == 50 {
break;
}
}
sndr.send(None);
}
}
struct ReceiveStruct;
impl ReceiveStruct {
fn receive(&self, rec: Receiver<Option<String>>) {
loop {
let recv_out = rec.recv().unwrap();
match recv_out {
Some(some_str) => println!("{}", some_str),
None => break,
}
}
}
}
struct SendReceiveStruct {
m_ss: SenderStruct,
m_sos: ReceiveStruct,
m_recv_hndlr: Option<thread::JoinHandle<()>>,
}
impl SendReceiveStruct {
fn new() -> Self {
SendReceiveStruct {
m_ss: SenderStruct {},
m_sos: ReceiveStruct {},
m_recv_hndlr: None,
}
}
fn start(&mut self) {
let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();
thread::spawn(move || self.m_ss.send(tx));
self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
}
fn wait_for_recevier(&mut self) {
self.m_recv_hndlr.unwrap().join();
}
}
fn main() {
println!("Hello, world!");
let mut ubs = SendReceiveStruct::new();
ubs.start();
ubs.wait_for_recevier();
}
But i m getting lifetime issues all over the place
$ cargo build
Compiling threads v0.1.0 (/root/learn-rust/threads)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:55:23
|
55 | thread::spawn(move || self.m_ss.send(tx));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 52:5...
--> src/main.rs:52:5
|
52 | / fn start(&mut self) {
53 | | let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();
54 | |
55 | | thread::spawn(move || self.m_ss.send(tx));
56 | | self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
57 | | }
| |_____^
= note: ...so that the types are compatible:
expected &mut SendReceiveStruct
found &mut SendReceiveStruct
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure#src/main.rs:55:23: 55:49 self:&mut SendReceiveStruct, tx:std::sync::mpsc::Sender<std::option::Option<std::string::String>>]` will meet its required lifetime bounds
--> src/main.rs:55:9
|
55 | thread::spawn(move || self.m_ss.send(tx));
Any pointers (or other references) would really help, and also any other possible approaches for the above problem ?
If you examine the signature of std::thread::spawn:
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send + 'static,
and its documentation closely:
The 'static constraint means that the closure and its return value must have a lifetime of the whole program execution. The reason for this is that threads can detach and outlive the lifetime they have been created in.
However, the &mut self value closure closes over may not live long enough. One way to overcome that is to clone the value the closure actually uses:
#[derive(Clone)]
struct SenderStruct;
#[derive(Clone)]
struct ReceiveStruct;
impl SendReceiveStruct {
fn start(&mut self) {
let (tx, rx): (Sender<Option<String>>, Receiver<Option<String>>) = channel();
thread::spawn({
let ss = self.m_ss.clone();
move || ss.send(tx)
});
self.m_recv_hndlr = Some(thread::spawn({
let sos = self.m_sos.clone();
move || sos.receive(rx)
}));
}
fn wait_for_recevier(&mut self) {
self.m_recv_hndlr.take().unwrap().join();
}
}
Except for several other minor issues, your code now compiles.

How can I write a boxed closure which mutates a reference to a struct?

I have some code that looks like this:
type Callback<T> = Box<Fn(&T) -> ()>;
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<String> {
Box::new(|new_name| {
self.name = *new_name;
})
}
}
This code doesn't compile because the closure requires the static lifetime. However I'm unsure if this will resolve the question and because there aren't explicit lifetimes, it's not immediately clear to me what I'd need to do to resolve that.
Here is an example of the compilation error:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 8:5...
--> src/lib.rs:8:5
|
8 | / fn name_updater(&mut self) -> Callback<String> {
9 | | Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
12 | | }
| |_____^
note: ...so that the type `[closure#src/lib.rs:9:18: 11:10 self:&mut &mut Foo]` will meet its required lifetime bounds
--> src/lib.rs:9:9
|
9 | / Box::new(|new_name| {
10 | | self.name = *new_name;
11 | | })
| |__________^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r std::string::String) + 'static)>
found std::boxed::Box<dyn for<'r> std::ops::Fn(&'r std::string::String)>
How can I write a closure that is capable of mutating the struct's name property?
You need to bound a lifetime to your closure because you borrow something aka &mut self:
type Callback<'a, T> = Box<dyn FnMut(&T) -> () + 'a>;
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater(&mut self) -> Callback<str> {
Box::new(move |new_name| {
self.name.replace_range(.., new_name);
})
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}
Also note that you don't need to use a box:
#[derive(Debug)]
struct Foo {
name: String,
}
impl Foo {
fn name_updater<'a>(&'a mut self) -> impl FnMut(&str) -> () + 'a {
move |new_name| {
self.name.replace_range(.., new_name);
}
}
}
fn main() {
let mut foo = Foo {
name: String::from("foo"),
};
foo.name_updater()("bar");
println!("{:?}", foo);
}

Resources