将Arc <Future>移动到线程池中

时间:2019-11-21 17:41:10

标签: rust async-await threadpool

我有一个简单的示例(configured),其中我首先使用Box :: pin()将未来转移到本地执行器中。

use std::collections::BTreeMap;
use futures::executor::LocalPool;
use futures::task::SpawnExt;
use std::sync::Arc;

async fn foo(input: i32) -> i32 {
    println!("foo {}", input);
    42 + input
}


fn code() {
    let mut pool = LocalPool::new();
    let mut map: BTreeMap<i32, _> = BTreeMap::new();
    map.insert(1, Box::pin(foo(1)));
    map.insert(2, Box::pin(foo(2)));

    let mut two = map.get_mut(&2).unwrap();
    let mut one = map.get_mut(&1).unwrap();

    let spawner = pool.spawner();
    spawner.spawn(async move { one.await; });
//    println!("one: {} two: {}", one, two);
}


fn code2() {
    let mut pool = LocalPool::new();
    let mut map: BTreeMap<i32, _> = BTreeMap::new();
    map.insert(1, Arc::pin(foo(1)));
    map.insert(2, Arc::pin(foo(2)));

    let mut two = map.get_mut(&2).unwrap();
    let mut one = map.get(&1).unwrap();

    let spawner = pool.spawner();
    let one = Arc::get_mut(&mut one.clone());
    spawner.spawn(async move { one.await; });
//    println!("one: {} two: {}", one, two);
}

fn main() {
    code();
}

在函数code2()中,我将其替换为Arc,因为我想使用线程池而不是localpool。 (未显示,因为在操场上不可用)。不幸的是,它与

有关
error[E0308]: mismatched types
  --> src/main.rs:37:28
   |
37 |     let one = Arc::get_mut(&mut one.clone()).unwrap();
   |                            ^^^^^^^^^^^^^^^^ expected struct `std::sync::Arc`, found struct `std::pin::Pin`
   |
   = note: expected type `&mut std::sync::Arc<_>`
              found type `&mut std::pin::Pin<std::sync::Arc<impl core::future::future::Future>>`

error: aborting due to previous error

ArcPin授权的未来转移到线程池中的合适方法是什么?

1 个答案:

答案 0 :(得分:0)

这可能不是问题。只要还有Box :: pin,也可以用弧线完成。

   fn thread_pool() {
        use futures::executor::ThreadPool;
        use async_std::sync::Mutex;
        let pool = ThreadPool::new().unwrap();

        let mut map: BTreeMap<i32, _> = BTreeMap::new();
        let fut =  Arc::new(Mutex::new(Box::pin(async {1})));
        map.insert(1,fut);

        let mut one = map.get(&1).unwrap().clone();

        pool.spawn(async move { 
            let mut guard = one.lock().await;
            let x  = (&mut *guard).await;
        });

    }

但是可能不是必需的,并且可能导致不确定的行为。例如,一旦将来完成,地图便会引用可能要访问的死去的未来。因此,正确的解决方案不是首先将未来存储在地图中。使用Box::pin就足够了

fn thread_pool() {
    use futures::executor::ThreadPool;
    let mut pool = ThreadPool::new().unwrap();
    let fut = Box::pin(async {1});

    pool.spawn(async move { 
        let x :i32 = fut.await;
    });
}