2017-04-18 42 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

相關問題