I am trying to implement a BFS algorithm to check whether a graph is a tree using Rust. I am an absolute beginner in Rust and I am confused with lifetime specification when it comes to threads. My code currently looks like this:
The graph is passed as adjacency matrix named adj_mat which is a vector of vectors. Nodes visited will be marked as true in the visited vector. And the parent vector stores the parent of each node visited. The function is_tree_parallel will call the bfs function, which will then spawn a new thread for each child of the current thread. This algorithm works fine when I use adj_mat, visited and parent vector as global variables.
fn is_tree_parallel(adj_mat: &Vec<Vec<usize>>, nodes: usize) {
let mut visited = vec![false; nodes + 1];
let mut parent = vec![0; nodes + 1];
let mut node_current = 1;
bfs(&mut parent, &adj_mat, &mut visited, node_current, nodes);
// Do checking of visited array and CYCLE (shared memory variable used to
// detect cycle) and decide whether it is a tree
}
When I use below function to spawn new threads, this is giving me errors like:
cannot infer an appropriate lifetime due to conflicting requirements first, the lifetime cannot outlive the expression.
I understand that this is due to the recursive calls inside the bfs function.
fn bfs(mut parent: &mut Vec<usize>, adj_mat: &Vec<Vec<usize>>, mut visited: &mut Vec<bool>, mut currentnode: usize, nodes: usize) {
visited[currentnode as usize] = true;
for i in 0..nodes {
if adj_mat[currentnode - 1][i as usize] == 1 && (i + 1) != parent[currentnode] {
if visited[i + 1 ] {
CYCLE = true;
return;
} else {
if RUNTHREADS < NTHREADS { //RUNTHREADS and NTHREADS will limit the number of threads spawned
RUNTHREADS += 1;
let mut visited = Arc::new(Mutex::new(visited));
let mut parent = Arc::new(Mutex::new(parent));
let adj_mat = Arc::new(adj_mat);
let visited = visited.clone();
let parent = parent.clone();
let adj_mat = adj_mat.clone();
thread::spawn(move || {
let visited = visited.lock().unwrap();
let parent = parent.lock().unwrap();
bfs(&mut parent, &adj_mat, &mut visited, i, nodes);
}).join();
} else {
bfs(parent, adj_mat, visited, i, nodes);
}
}
}
}
}
The error that I receive:
src/main.rs:134:69: 134:76 error: cannot infer an appropriate lifetime due to conflicting requirements [E0495]
src/main.rs:134 let mut visited = Arc::new(Mutex::new(visited));
src/main.rs:134:49: 134:57 note: first, the lifetime cannot outlive the expression at 134:48...
src/main.rs:134 let mut visited = Arc::new(Mutex::new(visited));
src/main.rs:134:49: 134:57 note: ...so that a type/lifetime parameter is in scope here
src/main.rs:134 let mut visited = Arc::new(Mutex::new(visited));
src/main.rs:134:49: 134:78 note: but, the lifetime must be valid for the call at 134:48...
src/main.rs:134 let mut visited = Arc::new(Mutex::new(visited));
src/main.rs:134:58: 134:77 note: ...so that argument is valid for the call
src/main.rs:134 let mut visited = Arc::new(Mutex::new(visited));
Am I doing it correct? How can I correct them? Is there any other way to achieve these recursive calls using threads?
Related
Since Iter's "all" fn takes type FnMut is it possible to update the element while checking for condition and short circuiting? Though I understand it is not supposed to, but what prevents it from updating the value?
fn main() {
let a = ["as", "zz"];
let mut iter = a.iter();
iter.all(|& (mut x)| {x = "cc"; true});
for z in a.iter(){
println!("{z}");
}
}
Above prints
as
zz
In above case why setting "x = cc" not work?
Or Alternatively why does Iter "all" method takes F of type FnMut and not Fn when it is not supposed to mutate but only validate for condition
x = "cc" does not change the value referred by x, instead it changes the reference itself (i.e. it makes it refer to another value), as evidenced by this example:
fn main() {
let a = ["as", "zz"];
let mut iter = a.iter();
iter.all(|&(mut x)| {
println!("before: {:?}", x as *const _);
x = "cc";
println!("after: {:?}", x as *const _);
true});
for z in a.iter(){
println!("{z}");
}
}
Playground
Note that this has nothing to do with the fact that the closure is FnMut, which only means that it may change any captured values as in:
fn main() {
let a = ["as", "zz"];
let mut count = 0;
let mut iter = a.iter();
iter.all(|&_x| {
count += 1; // This is possible because the closure is `FnMut`
true});
println!("Count: {count}");
for z in a.iter(){
println!("{z}");
}
}
Playground
Do not be mistaken! A function implementing FnMut means that it captures a receiving context mutably. It does not mean that its items may be modified from its original source.
let mut k = 0;
assert_eq!((10..15)..all(|x| {
k += 1;
x > k
}), true);
Given
let mut iter = a.iter();
we have an iterator the items of which are references to elements in vector a. And these references are immutable. In order to have an iterator which allows you to mutate the items in a vector, use iter_mut.
let iter = a.mut_iter();
iter.all(|x| { *x = "cc"; true});
for z in a.iter(){
println!("{z}");
}
This would still not require FnMut in particular, since it does not capture any context other than the items iterated on. The adaptor all (and many other iterator adaptors) were designed to constrain to FnMut so that the closures passed as their first parameter are allowed to keep and manipulate some external state for whichever logic they intend to do. Since the closure is called sequentially in the same thread, this is always memory safe.
See also:
What's the difference between placing "mut" before a variable name and after the ":"?
When does a closure implement Fn, FnMut and FnOnce?
I have a question for you, regarding my 'idx' structure and it's lifetimes... This structure is a cloneable multi threaded object.
This code works, how is it that moving 'idx' one layer up suddenly meant it didn't satify the 'static' lifetime requirement.
main() {
let w = webtask::Webtask::new();
// Wait for threads to finish
}
pub fn new() -> Self {
let (tx, rx) = oneshot::channel();
let mut idx = fastauth::createindex();
idx.load_index("users.dat.idx");
let lookup= warp::path!("lookup" / String).map(move |name| { Webtask::do_lookup(idx.clone(),name) });
let routes = lookup; //hello.or(lookup).or(check);
let (_addr, server) = warp::serve(routes).bind_with_graceful_shutdown(([127, 0, 0, 1], 3030), async {
rx.await.ok();
});
let thread = tokio::task::spawn(server);
Webtask {thread,tx}
}
-------- However, when I try and move 'idx' to the outer layer function I get errors..
main() {
let mut idx = fastauth::createindex();
idx.load_index("users.dat.idx");
let w = webtask::Webtask::new(&idx);
// Here I plan to reuse 'idx' as it's really a global structure that will exist the entire time the program is running...
do_something_else(&idx);
// then wait for threads to finish...
exit_when_done();
}
...
pub fn new<'inf>(idx: &'inf fastauth::Idx) -> Self {
let (tx, rx) = oneshot::channel();
let lookup= warp::path!("lookup" / String).map(move |name| { Webtask::do_lookup(idx.clone(),name) }); // IS CAPTURED HERE
let routes = lookup; //hello.or(lookup).or(check);
let (_addr, server) = warp::serve(routes).bind_with_graceful_shutdown(([127, 0, 0, 1], 3030), async { // IS REQUIRED TO LIVE AS LONG AS STATIC HERE.
rx.await.ok();
});
let thread = tokio::task::spawn(server);
// return our 'w' structure...
Webtask {thread,tx}
}
idx has lifetime 'inf but it needs to satisfy a 'static lifetime requirement
The important lines in the working code are:
let mut idx = fastauth::createindex();
let lookup= warp::path!("lookup" / String).map(
move |name| { Webtask::do_lookup(idx.clone(),name) });
Here, idx has type fastauth::Idx and is moved inside the closure, so the compiler can guarantee that idx will not be destroyed before the closure.
In the non-working code:
pub fn new<'inf>(idx: &'inf fastauth::Idx) -> Self {
let lookup= warp::path!("lookup" / String).map(
move |name| { Webtask::do_lookup(idx.clone(),name) });
Here, idx has type &fastauth::Idx so it is only a reference. That reference is moved inside the closure, but the real Idx is still outside the closure (in the main function), so the compiler can't guarantee that it won't get destroyed before the closure.
Depending on the reason why you wanted to move idx up, you have several solutions:
new can take idx by value instead of taking it by reference
pub fn new(idx: fastauth::Idx) -> Self {
but that means you won't be able to re-use idx in main after you call new, so not really a solution for you.
You can use reference-counting with Rc or Arc
use std::sync::Arc;
main() {
let mut idx = Arc::new (fastauth::createindex());
idx.load_index("users.dat.idx");
let w = webtask::Webtask::new(idx.clone());
// Here I plan to reuse 'idx' as it's really a global structure that will exist the entire time the program is running...
do_something_else(idx);
// then wait for threads to finish...
exit_when_done();
}
pub fn new(idx: Arc::<fastauth::Idx>) -> Self {
let (tx, rx) = oneshot::channel();
let lookup= warp::path!("lookup" / String).map(move |name| { Webtask::do_lookup(idx.clone(),name) }); // IS CAPTURED HERE
let routes = lookup; //hello.or(lookup).or(check);
let (_addr, server) = warp::serve(routes)
.bind_with_graceful_shutdown(
([127, 0, 0, 1], 3030),
async { // IS REQUIRED TO LIVE AS LONG AS STATIC HERE.
rx.await.ok();
});
let thread = tokio::task::spawn(server);
// return our 'w' structure...
Webtask {thread,tx}
}
Rc and Arc allow multiple contexts to share ownership of a value, so that the value only gets destroyed when the last reference goes out of scope.
You can use lazy_static to create a global immutable static value
use lazy_static;
lazy_static!{
static ref IDX: fastauth::Idx = {
let mut idx = fastauth::createindex();
idx.load_index("users.dat.idx");
idx
};
}
See the lazy_static crate for details.
Looking for a way to push in both Vec<Vec<>> and it's inner Vec<>. I do understand why it fails, but still struggle to find some graceful way to solve it.
fn example() {
let mut vec: Vec<Vec<i32>> = vec![];
vec.push(vec![]);
for i in &mut vec {
i.push(1);
if vec.len() < 10 {
vec.push(vec![]); // second mut borrow
}
}
}
The borrow checker won't allow you to iterate over a vector by reference and modify it during iteration. The reason for that is that modifying the vector can reallocate its storage, which would invalidate the references used for iteration. (And there is also the question of what it means to iterate over a changing vector, do you want to visit the elements added during iteration or just the elements that were present originally.)
The easiest fix that allows you to do what you want is to just iterate the vector using an index:
fn example() {
let mut vec: Vec<Vec<i32>> = vec![];
vec.push(vec![]);
let mut ind = 0;
while ind < vec.len() {
let i = &mut vec[ind];
i.push(1);
if vec.len() < 10 {
vec.push(vec![]);
}
ind += 1;
}
}
I'm having difficulty getting the borrow checker working for a simple iterative linked list builder.
fn main() {
let v = vec![1,5,3,8,12,56,1230,2,1];
let nodes = Vec::<Node>::with_capacity(v.len());
let mut root: Option<&mut Box<Node>> = None;
let mut prev: &Option<&mut Box<Node>> = &None;
for i in v {
let curr = Some(&mut Box::new(Node { value: i, next: None }));
match *prev {
Some(ref mut p) => {
p.next = curr;
prev = &mut p.next;
},
None => {
root = curr;
prev = &mut root;
}
}
}
}
struct Node<'a> {
value: i32,
next: Option<&'a mut Box<Node<'a>>>,
}
The errors I'm receiving when I try to compile:
linked_list.rs:8:30: 8:69 error: borrowed value does not live long enough
linked_list.rs:8 let curr = Some(&mut Box::new(Node { value: i, next: None }));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:4:49: 20:2 note: reference must be valid for the block suffix following statement 2 at 4:48...
linked_list.rs:4 let mut root: Option<&mut Box<Node>> = None;
linked_list.rs:5 let mut prev: &Option<&mut Box<Node>> = &None;
linked_list.rs:6
linked_list.rs:7 for i in v {
linked_list.rs:8 let curr = Some(&mut Box::new(Node { value: i, next: None }));
linked_list.rs:9 match *prev {
...
linked_list.rs:8:9: 8:71 note: ...but borrowed value is only valid for the statement at 8:8
linked_list.rs:8 let curr = Some(&mut Box::new(Node { value: i, next: None }));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
linked_list.rs:8:9: 8:71 help: consider using a `let` binding to increase its lifetime
linked_list.rs:8 let curr = Some(&mut Box::new(Node { value: i, next: None }));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
linked_list.rs:10:18: 10:27 error: cannot borrow immutable anonymous field `(prev:core::option::Some).0` as mutable
linked_list.rs:10 Some(ref mut p) => {
^~~~~~~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:15:17: 15:28 error: cannot assign to `root` because it is borrowed
linked_list.rs:15 root = curr;
^~~~~~~~~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:16:29: 16:33 note: borrow of `root` occurs here
linked_list.rs:16 prev = &mut root;
^~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:16:29: 16:33 error: cannot borrow `root` as mutable more than once at a time
linked_list.rs:16 prev = &mut root;
^~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:16:29: 16:33 note: previous borrow of `root` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `root` until the borrow ends
linked_list.rs:16 prev = &mut root;
^~~~
note: in expansion of for loop expansion
linked_list.rs:7:5: 19:6 note: expansion site
linked_list.rs:20:2: 20:2 note: previous borrow ends here
linked_list.rs:1 fn main() {
...
linked_list.rs:20 }
^
error: aborting due to 4 previous errors
What I'm trying to go for is fairly simple. We iterate through a Vec, creating a new node on each iteration. If prev is None this must be the start, so we make the root variable take ownership of that first node. If it's not, we update the previous node's next value to point to this node.
I'm new to Rust so I'm not sure where I'm going wrong. My interpretation is that the borrow checker isn't handling this well. It can't infer that the None branch in the match, containing the 'root' assignment, will only ever be called once, causing the two errors about root being borrowed twice. Am I correct?
Is this approach possible in Rust? Is there a more idiomatic way to do this sort of thing?
(A recursive approach is probably much easier but I'd like to complete an iterative one as a learning exercise.)
First of all, you should probably make sure you've read and understood the Rust Book chapters on Ownership and References and Borrowing. Your immediate problem is that you're borrowing things that aren't owned by anything, and will thus just disappear. You also have other problems like trying to mutate through an immutable pointer.
Let's get something that does, at least, work:
fn main() {
let v = vec![1,5,3,8,12,56,1230,2,1];
let mut root: Option<Box<Node>> = None;
for i in v.into_iter().rev() {
root = Some(Box::new(Node { value: i, next: root }));
}
println!("root: {}",
root.map(|n| n.to_string()).unwrap_or(String::from("None")));
}
struct Node {
value: i32,
next: Option<Box<Node>>,
}
impl std::fmt::Display for Node {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let mut cur = Some(self);
let mut first = true;
try!(write!(fmt, "["));
while let Some(node) = cur {
if !first { try!(write!(fmt, ", ")); }
first = false;
try!(write!(fmt, "{}", node.value));
cur = node.next.as_ref().map(|n| &**n);
}
try!(write!(fmt, "]"));
Ok(())
}
}
This constructs a list and shows how you can iteratively display it. Note the complete lack of borrows in the construction code.
I have cheated somewhat, in that I've iterated the vector backwards to construct the list.
The problem with the original code is that, even if you strip out everything that isn't necessary, down to something like this:
let v = vec![1,5,3,8,12,56,1230,2,1];
let mut v = v.into_iter();
let mut root: Option<Box<Node>> = None;
if let Some(i) = v.next() {
root = Some(Box::new(Node { value: i, next: None }));
let mut prev: &mut Box<Node> = root.as_mut().unwrap();
for i in v {
let curr = Some(Box::new(Node { value: i, next: None }));
prev.next = curr;
prev = prev.next.as_mut().unwrap();
}
}
You still end up in a situation where the compiler sees you mutating a thing you've borrowed by a second path. It's not quite smart enough to realise that re-assigning prev doesn't actually create any aliases. On the other hand, if you break the loop into an equivalent recursion:
if let Some(i) = v.next() {
root = Some(Box::new(Node { value: i, next: None }));
fn step<It>(prev: &mut Box<Node>, mut v: It) where It: Iterator<Item=i32> {
if let Some(i) = v.next() {
let curr = Some(Box::new(Node { value: i, next: None }));
prev.next = curr;
step(prev.next.as_mut().unwrap(), v)
}
}
step(root.as_mut().unwrap(), v);
}
Then it's totally fine with it. Sadly, even with optimisations turned on, Rust doesn't perform tail call elimination in this case. So between borrow checker limitations and a lack of guaranteed tail call elimination, this design might be impossible to do in safe code.
I've run into this problem myself; loops and &mut pointers don't always play nicely with one another. You can work around this by switching to RefCell, with its associated runtime cost, although this then complicates iterating over such a list in a loop. Another alternative is to use usizes instead of pointers, and have all the nodes allocated into a Vec somewhere, although that introduces bounds checking overhead.
Failing all that, there's unsafe code, which lets you write more or less exactly what you would write in another language like C or C++, but without Rust's usual safety guarantees.
At the end of the day, writing data structures that are not just wrappers around an existing data structure in safe Rust without overhead is borderline impossible. It's why the fundamental data structures in Rust are all written using some amount of unsafe code.
I can't figure out what does this error in Rust mean:
error: lifetime of non-lvalue is too short to guarantee its contents can be safely reborrowed
What's a non-lvalue? (I suspect is not a right value).
I want to understand what the errror means and to be able to modify "objects" from a vector of mutable references.
This is a minimum test case to produce the error. I insert in a vector a mutable reference to a struct, and then I try to modify the pointed struct.
struct Point {
x: uint,
y: uint
}
fn main() {
let mut p = Point { x: 0, y: 0};
p.x += 1; // OK, p owns the point
let mut v: Vec<&mut Point> = Vec::new();
v.push(&mut p);
// p.x += 1 // FAIL (expected), v has borrowed the point
let p1:&mut Point = *v.get_mut(0); // ERROR, lifetime of non-lvalue...
// never reached this line
// p1.x += 1;
}
Let's go over what you're trying to do here:
let p1:&mut Point = *v.get_mut(0);
*v.get_mut(0) returns a mutable reference to first the mutable reference in the vector, then dereferences it. If this compiled, you would end up with two mutable references to the same object: one in the vector, the other in the p1 variable. Rust is rejecting this because it's not safe.
By far the best solution is to make the vector the owner of your Point objects. ie. use a Vec<Point> instead of a Vec<&mut Point.
If you need something more complicated, you can use a RefCell for dynamically checked borrowing:
use std::cell::RefCell;
struct Point {
x: uint,
y: uint
}
fn main() {
let p = RefCell::new(Point { x: 0, y: 0});
p.borrow_mut().x += 1;
let mut v: Vec<&RefCell<Point>> = Vec::new();
v.push(&p);
let p1 = v.get(0);
p1.borrow_mut().x += 1;
p.borrow_mut().x += 1;
}