I want to store a closure in struct that implements Clone, so i'm code this:
use std::rc::Rc;
type Closure = Box<dyn Fn() -> ()>;
#[derive(Clone)]
struct A {
closure: Option<Rc<Closure>>,
}
impl A {
pub fn new() -> A {
A { closure: None }
}
pub fn closure(&self) -> Option<Rc<Closure>> {
self.closure.clone()
}
pub fn set_closure(&mut self, closure: Closure) -> &mut Self {
self.closure = Some(Rc::new(closure));
self
}
}
fn main() {
let mut a: A = A::new();
a.set_closure(Box::new(|| -> () { println!("Works fine!") }));
(a.closure().unwrap())();
}
Now I want to test this code by borrowing a variable of current scope. It's important to keep a reference in main function, because i need to use it after.
I code this:
use std::cell::RefCell;
fn main() {
let mut a: A = A::new();
let value: Rc<RefCell<i8>> = Rc::new(RefCell::new(0));
println!("Value = {}", value.borrow());
a.set_closure(Box::new(|| -> () {
*value.borrow_mut() = 1;
}));
(a.closure().unwrap())();
println!("New value = {}", value.borrow());
}
But I get this error:
Compiling playground v0.0.1 (/playground)
error[E0597]: `value` does not live long enough
--> src/main.rs:34:38
|
34 | a.set_closure(Box::new(|| -> () { *value.borrow_mut() = 1; }));
| ---------------------^^^^^---------------------
| | | |
| | | borrowed value does not live long enough
| | value captured here
| cast requires that `value` is borrowed for `'static`
...
38 | }
| - `value` dropped here while still borrowed
Would anyone know what I need to do please.
Thank you for your reply in advance.
Rcs are shared by cloning, which increments their reference count. But you pass a reference to it to the closure, which is perhaps defeating the point of using an Rc in the first place. As the error says, the closure is holding a reference to value after value is dropped.
You probably intended to write something like this, which clones the Rc and moves the clone into the closure:
let cloned_value = value.clone();
a.set_closure(Box::new(move || *cloned_value.borrow_mut() = 1));
Or (my preference) avoiding introducing a new binding in the outer scope:
a.set_closure(Box::new({
let value = value.clone();
move || *value.borrow_mut() = 1
}));
Related
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.
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
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.
Here is my code
struct test_loop {
is_break: bool,
}
impl test_loop {
fn run_forever<F>(&mut self, mut f: F)
where
F: FnMut() -> (),
{
self.is_break = false;
loop {
f();
if self.is_break {
break;
}
}
}
fn breakit(&mut self) {
self.is_break = true;
}
}
fn main() {
let mut l = test_loop { is_break: false };
let f = || {
l.breakit();
};
l.run_forever(f);
}
The code is simple, and I don't want to skip calling l.breakit() in the closure. Now the compiler tells me there is a second mutable borrow problem:
error[E0499]: cannot borrow `l` as mutable more than once at a time
--> src/main.rs:26:5
|
23 | let f = || {
| -- first mutable borrow occurs here
24 | l.breakit();
| - first borrow occurs due to use of `l` in closure
25 | };
26 | l.run_forever(f);
| ^ - first borrow later used here
| |
| second mutable borrow occurs here
I used a RefCell to fix the compilation problem, but the thread still panics during run-time. Should I remove the l.xxx in the closure? Or there's some way to make the code act like it is running in C++ or another language?
if f() can change test_loop state, then it's natural to add this reference to its signature. This solves the second borrow problem.
fn run_forever<F>(&mut self, mut f: F)
where
F: FnMut(&mut Self) -> (),
{
// call f(self) instead of f()
}
// main
let f = |l: &mut test_loop| {
l.breakit();
};
I try to send an unwrapped string reference to a static method implemented for a struct. Here is a simplified code:
fn main() {
let a = A {p: Some("p".to_string())};
a.a();
}
struct A {
p: Option<String>
}
impl A {
fn a(self) -> Self {
Self::b(&self.p.unwrap());
self
}
fn b(b: &str) {
print!("b: {}", b)
}
}
It fails:
error[E0382]: use of partially moved value: `self`
--> src/main.rs:14:13
|
13 | Self::b(&self.p.unwrap());
| ------ value moved here
14 | self
| ^^^^ value used here after move
|
= note: move occurs because `self.p` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
I think implementing the Copy trait is not a solution. How can I unwrap p and pass it as a &str to b in that context?
I changed my code as suggested in Can't borrow File from &mut self (error msg: cannot move out of borrowed content):
fn main() {
let a = A {p: Some("p".to_string())};
a.a();
}
struct A {
p: Option<String>
}
impl A {
fn a(self) -> Self {
let c = self.p.as_ref().unwrap();
Self::b(&c);
self
}
fn b(b: &str) {
print!("b: {}", b)
}
}
Which results in a different error:
error[E0505]: cannot move out of `self` because it is borrowed
--> src/main.rs:15:13
|
13 | let c = self.p.as_ref().unwrap();
| ------ borrow of `self.p` occurs here
14 | Self::b(&c);
15 | self
| ^^^^ move out of `self` occurs here
As discussed in Can't borrow File from &mut self (error msg: cannot move out of borrowed content), you can't call unwrap on a borrowed value because unwrap takes ownership of the value.
Changing to as_ref borrows from the value self. You are not allowed to move a value (which includes returning that value) while any references to it are outstanding. That means you need to constrain the life of the borrow to end before the value needs to be moved:
fn a(self) -> Self {
{
let c = self.p.as_ref().unwrap();
Self::b(c);
}
self
}
It may be an artifact of your example, but the code is pretty strange. I'd have written it as
impl A {
fn a(self) -> Self {
self.b();
self
}
fn b(&self) {
print!("b: {}", self.p.as_ref().unwrap())
}
}
Or
impl A {
fn a(&self) {
print!("a: {}", self.p.as_ref().unwrap())
}
}