简体   繁体   English

Rust 将一堆任务变成在线程池上执行的未来的成语是什么?

[英]What is the Rust idiom for turning a bunch of tasks into futures that are executed on a thread pool?

In java I would use an ExecutorService that is a thread pool with a fixed size and submit(Callable) s to it and then get() the results.在 java 中,我将使用一个ExecutorService ,它是一个具有固定大小的线程池,并向其submit(Callable) s,然后get()结果。

What is the idiom that matches this in Rust? Rust中与此匹配的成语是什么? I could thread::spawn() a bunch of tasks and join() them, but it would create a thread per task, and I want to limit the number of concurrent threads.我可以thread::spawn()一堆任务和join()它们,但它会为每个任务创建一个线程,我想限制并发线程的数量。

In order to make things a little more concrete, here is a rough sketch of some code:为了使事情更具体一些,这里是一些代码的粗略草图:

let a4 = thread_pool.spawn(|| svg.compute_stitches("path674"));
let a1 = thread_pool.spawn(|| svg.compute_stitches("path653"));
let a2 = thread_pool.spawn(|| svg.compute_stitches("g659"));
let a3 = thread_pool.spawn(|| svg.compute_stitches("path664"));
let a5 = thread_pool.spawn(|| svg.compute_stitches("path679"));

stitcher.stitch(a1.join());
stitcher.stitch(a2.join());
stitcher.next_color();
stitcher.stitch(a3.join());
stitcher.next_color();
stitcher.stitch(a4.join());
stitcher.next_color();
stitcher.stitch(a5.join());

I have rolled my own solution for the time being.我暂时推出了自己的解决方案。 It looks like this:它看起来像这样:

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, RecvError};
use std::{panic, thread};

pub struct ThreadPool {
    channel: spmc::Sender<Mission>,
}

impl ThreadPool {
    pub fn new(thread_count: usize) -> ThreadPool {
        let (tx, rx) = spmc::channel();

        for _ in 0..thread_count {
            let rx2 = rx.clone();
            thread::spawn(move || Self::work_loop(rx2));
        }

        ThreadPool { channel: tx }
    }

    pub fn spawn<F, T: 'static>(&mut self, task: F) -> Answer<T>
    where
        F: FnOnce() -> T + std::panic::UnwindSafe + Send + 'static,
    {
        let (tx, rx) = mpsc::channel();

        let mission = Mission {
            go: Box::new(move || {
                let tmp = panic::catch_unwind(task);
                tx.send(tmp).unwrap()
            }),
        };

        self.channel.send(mission).unwrap();

        Answer { channel: rx }
    }

    fn work_loop(channel: spmc::Receiver<Mission>) {
        while let Ok(mission) = channel.recv() {
            (mission.go)();
        }
    }
}

struct Mission {
    go: Box<dyn FnOnce()>,
}

unsafe impl Send for Mission {}

pub struct Answer<T> {
    channel: Receiver<std::thread::Result<T>>,
}

impl<T> Answer<T> {
    pub fn get(self) -> Result<T, RecvError> {
        let tmp = self.channel.recv();

        match tmp {
            Ok(rval) => match rval {
                Ok(rval) => Ok(rval),
                Err(explosion) => panic::resume_unwind(explosion),
            },
            Err(e) => Err(e),
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM