Как вынести в impl блок кода, создающий отдельный поток?

Код, приведенный в первом блоке - работает.
Как вынести в отдельный impl часть, которая создаёт отдельный поток?
Типа, как во втором блоке кода, где помечено, что так не работает.
play_1

use std::time::{SystemTime, Instant};
use std::thread;
use thread::JoinHandle;


fn main() {

   let handle: JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> = thread::spawn(|| {
      let t21: SystemTime = SystemTime::now();
      let start_02 = Instant::now();
      let mut j: usize = 0;
      loop {
         if j == 10 { break; }
         j = j + 1;
      }
      let t22: SystemTime = SystemTime::now();
      let d2:(usize, SystemTime, SystemTime, core::time::Duration) = (j, t21, t22, start_02.elapsed());
      d2
   });

   
   let t11: SystemTime = SystemTime::now();
   let start_01 = Instant::now();
   let mut i: usize = 0;
   loop {
      if i == 10 { break; }
      i = i + 1;
   }
   let t12 = SystemTime::now();

   
   let d2 = handle.join().expect("thread panicked :...");

   println!("i = {:?} \nt11 = {:?} \nt12 = {:?}", i, t11, t12);
   println!("dt_01 = {:?}\n", start_01.elapsed());
   //
   println!("j = {:?} \nt21 = {:?} \nt22 = {:?}", &d2.0, &d2.1, &d2.2);
   println!("dt_02 = {:?}\n", &d2.3);
}

что-то типа такого:
play_2

use std::time::{SystemTime, Instant};
use std::thread;
use thread::JoinHandle;

struct Thd {
   a: usize, 
   b: SystemTime, 
   c: SystemTime,
   d: core::time::Duration,
}

impl Thd {

   pub fn new() -> JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> {

     thread::spawn(|| {
       let t21: SystemTime = SystemTime::now();
       let start_02 = Instant::now();
       let mut j: usize = 0;
       loop {
         if j == 1_000_000 { break; }
         j = j + 1;
       }
       let t22: SystemTime = SystemTime::now();
       
       let d: Thd = Thd01 {a: j, b: t21, c: t22, d:start_02.elapsed()};
       
       let d2:(usize, SystemTime, SystemTime, core::time::Duration) = (d.a, d.b, d.c, d.d);

       d2
     });
   }
}

fn main() {
   // Error `так не работает`:
   let handle: JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> = Thd::new();

   
   let t11: SystemTime = SystemTime::now();
   let start_01 = Instant::now();
   let mut i: usize = 0;
   loop {
      if i == 1_000_000 { break; }
      i = i + 1;
   }
   let t12 = SystemTime::now();

   
   let d2 = handle.join().expect("thread panicked :...");

   println!("i = {:?} \nt11 = {:?} \nt12 = {:?}", i, t11, t12);
   println!("dt_01 = {:?}\n", start_01.elapsed());
   //
   println!("j = {:?} \nt21 = {:?} \nt22 = {:?}", &d2.0, &d2.1, &d2.2);
   println!("dt_02 = {:?}\n", &d2.3);
}


update_01

play_3

use std::time::{SystemTime, Instant};
use std::thread;
use thread::JoinHandle;

struct Thd {
   a: usize, 
   b: SystemTime, 
   c: SystemTime,
   dt: core::time::Duration,
}

impl Thd {

   pub fn new() -> JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> {
   
     let handle: JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> =
     thread::spawn(|| {
       let t21: SystemTime = SystemTime::now();
       let start_02 = Instant::now();
       let mut j: usize = 0;
       loop {
         if j == 1_000_000 { break; }
         j = j + 1;
       }
     
       let t22: SystemTime = SystemTime::now();
       let d: Thd = Thd {a: j, b: t21, c: t22, dt:start_02.elapsed()};
       let d2:(usize, SystemTime, SystemTime, core::time::Duration) = (d.a, d.b, d.c, d.dt);
       d2
     });
     handle
   }
}

fn main() {
   // `так работает`:
   let handle: JoinHandle<(usize, SystemTime, SystemTime, core::time::Duration)> = Thd::new();

   
   let t11: SystemTime = SystemTime::now();
   let start_01 = Instant::now();
   let mut i: usize = 0;
   loop {
      if i == 1_000_000 { break; }
      i = i + 1;
   }
   let t12 = SystemTime::now();

   
   let d2 = handle.join().expect("thread panicked :...");

   println!("i = {:?} \nt11 = {:?} \nt12 = {:?}", i, t11, t12);
   println!("dt_01 = {:?}\n", start_01.elapsed());
   //
   println!("j = {:?} \nt21 = {:?} \nt22 = {:?}", &d2.0, &d2.1, &d2.2);
   println!("dt_02 = {:?}\n", &d2.3);
}

/*

i = 1000000 
t11 = SystemTime { tv_sec: 1737389697, tv_nsec: 383198522 } 
t12 = SystemTime { tv_sec: 1737389697, tv_nsec: 385890160 }
dt_01 = 2.931694ms

j = 1000000 
t21 = SystemTime { tv_sec: 1737389697, tv_nsec: 383252593 } 
t22 = SystemTime { tv_sec: 1737389697, tv_nsec: 386045474 }
dt_02 = 2.792891ms

*/

Ответы (1 шт):

Автор решения: extrn

Хочу из main для потока в impl задавать количество итераций

Внесите, пожалуйста, ответ

С учетом того, что Thd это все-таки не сам тред, а результат его работы, тем более, что использоваться он может и без создания треда, есть смысл вообще исключить упоминание тредов из имплементации, а также переименовать его, ну и немного обобщить.

use std::fmt;
use std::thread;
use std::time::{Duration, Instant, SystemTime};

#[derive(Debug)]
pub struct Metrics<T> {
    result: T,
    start: SystemTime,
    stop: SystemTime,
    elapsed: Duration,
}

impl<T> Metrics<T> {
    pub fn gather(f: impl FnOnce() -> T) -> Self {
        let start = SystemTime::now();
        let instant = Instant::now();
        let result = f();
        let stop = SystemTime::now();
        let elapsed = instant.elapsed();
        Self { result, start, stop, elapsed }
    }
}

impl<T: fmt::Display> fmt::Display for Metrics<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "result  = {}", self.result)?;
        writeln!(f, "start   = {:?}", self.start)?;
        writeln!(f, "stop    = {:?}", self.stop)?;
        writeln!(f, "elapsed = {:?}", self.elapsed)?;
        Ok(())
    }
}

fn main() {
    fn work() -> Metrics<usize> {
        Metrics::gather(|| {
            let mut i: usize = 0;

            loop {
                if i == 1_000_000 { break; }
                i = i + 1;
            }
            i
        })
    }

    let handle = thread::spawn(work);
    let result1 = work();
    let result2 = handle.join().unwrap();
    println!("main\n{result1}");
    println!("spawned\n{result2}");
}
main
result  = 1000000
start   = SystemTime { tv_sec: 1737472310, tv_nsec: 712452124 }
stop    = SystemTime { tv_sec: 1737472310, tv_nsec: 714353146 }
elapsed = 1.900872ms

spawned
result  = 1000000
start   = SystemTime { tv_sec: 1737472310, tv_nsec: 712530206 }
stop    = SystemTime { tv_sec: 1737472310, tv_nsec: 714439057 }
elapsed = 1.908791ms

Песочница

→ Ссылка