I have read the following question:
and elaborated some more complex tests. The following code add a &str parameter for the functions and it works:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
let one: &str = "Alpha";
let two: &str = "Beta";
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
My understanding is that this works because Copy Trait is implemented for str. Now consider the following example:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
let one: String = String::from("Alpha");
let two: String = String::from("Beta");
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
I am getting this at compile time:
error[E0382]: use of moved value: `one`
--> src\main.rs:19:42
|
10 | let one: String = String::from("Alpha");
| --- move occurs because `one` has type `String`, which does not implement the `Copy` trait
...
19 | let thread_a = thread::spawn(move || { a(&one) });
| ^^^^^^^ --- use occurs due to use in closure
| |
| value moved into closure here, in previous iteration of loop
error[E0382]: use of moved value: `two`
--> src\main.rs:20:42
|
11 | let two: String = String::from("Beta");
| --- move occurs because `two` has type `String`, which does not implement the `Copy` trait
...
20 | let thread_b = thread::spawn(move || { b(&two) });
| ^^^^^^^ --- use occurs due to use in closure
| |
| value moved into closure here, in previous iteration of loop
error: aborting due to 2 previous errors
EDIT1
It seems it can be solved with the use of .clone() But now consider the following code:
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let one: String = String::from("Alpha");
let two: String = String::from("Beta");
let scheduler = thread::spawn(|| {
let wait_time = Duration::from_millis(500);
// Make this an infinite loop
// Or some control path to exit the loop
for _ in 0..5 {
let start = Instant::now();
eprintln!("Scheduler starting at {:?}", start);
let one = one.clone();
let two = two.clone();
let thread_a = thread::spawn(move || { a(&one) });
let thread_b = thread::spawn(move || { b(&two) });
thread_a.join().expect("Thread A panicked");
thread_b.join().expect("Thread B panicked");
let runtime = start.elapsed();
if let Some(remaining) = wait_time.checked_sub(runtime) {
eprintln!(
"schedule slice has time left over; sleeping for {:?}",
remaining
);
thread::sleep(remaining);
}
}
});
scheduler.join().expect("Scheduler panicked");
}
fn a(a: &str) {
eprintln!("{}", a);
thread::sleep(Duration::from_millis(100))
}
fn b(b: &str) {
eprintln!("{}", b);
thread::sleep(Duration::from_millis(200))
}
I am now getting different error codes:
error[E0373]: closure may outlive the current function, but it borrows `two`, which is owned by the current function
--> src\main.rs:11:35
|
11 | let scheduler = thread::spawn(|| {
| ^^ may outlive borrowed value `two`
...
21 | let two = two.clone();
| --- `two` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src\main.rs:11:21
|
11 | let scheduler = thread::spawn(|| {
| _____________________^
12 | | let wait_time = Duration::from_millis(500);
13 | |
14 | | // Make this an infinite loop
... |
38 | | }
39 | | });
| |______^
help: to force the closure to take ownership of `two` (and any other referenced variables), use the `move` keyword
|
11 | let scheduler = thread::spawn(move || {
| ^^^^^^^
error[E0373]: closure may outlive the current function, but it borrows `one`, which is owned by the current function
--> src\main.rs:11:35
|
11 | let scheduler = thread::spawn(|| {
| ^^ may outlive borrowed value `one`
...
20 | let one = one.clone();
| --- `one` is borrowed here
|
note: function requires argument type to outlive `'static`
--> src\main.rs:11:21
|
11 | let scheduler = thread::spawn(|| {
| _____________________^
12 | | let wait_time = Duration::from_millis(500);
13 | |
14 | | // Make this an infinite loop
... |
38 | | }
39 | | });
| |______^
help: to force the closure to take ownership of `one` (and any other referenced variables), use the `move` keyword
|
11 | let scheduler = thread::spawn(move || {
| ^^^^^^^
error: aborting due to 2 previous errorsù