2017-04-18 44 views
2

我有以下代码:如何删除传递给futures-cpupool的封闭环境?

extern crate futures; 
extern crate futures_cpupool; 
extern crate tokio_timer; 

use std::time::Duration; 

use futures::Future; 
use futures_cpupool::CpuPool; 
use tokio_timer::Timer; 

fn work(foo: Foo) { 
    std::thread::sleep(std::time::Duration::from_secs(10)); 
} 

#[derive(Debug)] 
struct Foo { } 

impl Drop for Foo { 
    fn drop(&mut self) { 
     println!("Dropping Foo"); 
    } 
} 

fn main() { 
    let pool = CpuPool::new_num_cpus(); 

    let foo = Foo { }; 

    let work_future = pool.spawn_fn(|| { 
     let work = work(foo); 

     let res: Result<(),()> = Ok(work); 
     res 
    }); 

    println!("Created the future"); 

    let timer = Timer::default(); 
    let timeout = timer.sleep(Duration::from_millis(750)) 
     .then(|_| Err(())); 

    let select = timeout.select(work_future).map(|(win, _)| win); 

    match select.wait() { 
     Ok(()) => { }, 
     Err(_) => { }, 
    } 
} 

看来这个代码不执行Foo::drop - 打印任何消息。

我预计foo一旦timeout未来解决在select,因为它是一个关闭的环境的一部分,传递到下降的未来。

如何使其执行Foo::drop

+1

它看起来像'foo'正在一个线程中使用,超过程序终止。参看https://users.rust-lang.org/t/stopping-a-thread/6328。我不知道是否http://stackoverflow.com/questions/26199926/how-to-terminate-or-suspend-a-rust-thread-from-another-thread是否足以回答你的问题? – ArtemGr

回答

3

documentation for CpuPool states:因为有一个开放的句柄CpuPool或有对他们运行工作

工人与线程池相关的线程保持活力这么久。一旦所有的工作都被排空,所有的引用都消失了,工作线程就会关闭。

此外,您从main转让foo所有权关闭,然后其转移到workwork将在该块的结尾处下降foo。但是,work也正在执行阻止的睡眠操作。这种睡眠被视为在线程上运行的工作。

当主线程退出时,睡眠仍在继续,这会立即将程序和所有线程断开,而无需任何时间清理。

正如在How to terminate or suspend a Rust thread from another thread?(和其他语言的其他问题)中指出的那样,没有安全的方法来终止线程。

我预计foo将在select一旦超时未来解析下降,因为它是一个封闭,传递给未来下跌的环境的一部分。

未来实际上并没有 “有” 关闭或foo。所有它是一个句柄到线程:

pub struct CpuFuture<T, E> { 
    inner: Receiver<thread::Result<Result<T, E>>>, 
    keep_running_flag: Arc<AtomicBool>, 
} 

奇怪的是,the docs say

如果返回的将来被丢弃那么这个CpuPool尝试取消计算,如果可能的话。也就是说,如果计算正处于工作中,那么在可能的情况下将会中断

不过,我没有看到任何Drop实施CpuFuture所以我看不出它怎么可能(或安全)。而不是Drop,线程池本身运行Future。当这个未来被轮询时,它会检查接收器是否被丢弃。此行为由oneshot::Receiver提供。然而,这与线程无关,这是未来视角之外的事情。

+3

- “*但是,我看不到Drop for CpuFuture的任何实现*” - Drop是在Receiver中的(参见https://github.com/alexcrichton/futures-rs/blob/master /src/sync/oneshot.rs)。 – ArtemGr

+0

那么,真的没有办法自动使用期货来调用析构函数? –

+0

@MichaelPankov我认为这是从错误的角度来看它。在Rust中,析构函数不保证运行,但是当它们总是自动运行时。期货也不例外 - 当变量自然超出范围时,将调用析构函数。你的问题围绕着这样一个事实,即你已经开始了一个在主线程退出时仍然可以工作的线程。问题与期货完全正交。 – Shepmaster

相关问题