2013-07-24 27 views
1

我遇到了lifetimes和借用點的問題。我已閱讀手冊和借用的指針教程,但是...我仍然卡住了。DuplexStream跨任務和關閉

main.rs素描

fn main() { 
    let (db_child, repo_child):(DuplexStream<~str, ~str>, DuplexStream<~str, ~str>) = DuplexStream(); 
    do spawn { 
     slurp_repos(&repo_child); 
    } 
} 

素描的repos.rs

fn slurp_repos(chan: &'static DuplexStream<~str, ~str>) { 
    ... 
    do request.begin |event| { 
     ... 
     chan.send(api_url); 
    } 
} 

當我編譯這些模塊,main.rs有以下錯誤:

main.rs:21:20: 21:31 error: borrowed value does not live long enough 
main.rs:21   slurp_repos(&repo_child); 
           ^~~~~~~~~~~ 
note: borrowed pointer must be valid for the static lifetime... 
main.rs:13:10: 1:0 note: ...but borrowed value is only valid for the block at 13:10 
error: aborting due to previous error 

我不能很弄清楚如何聲明我的DuplexStreams生命週期是靜態的。或者,這可能是用於slurp_repos函數類型的錯誤方法。

如果你想看到完整的上下文:

+0

不應該將repo_child定義爲託管('@')嗎? – snf

+0

我無法弄清楚如何聲明@repo_child。你有一個編譯的例子嗎? – Ozten

+1

我想解決這個問題的一種方法是在閉包中更新狀態對象,然後在從request.begin返回後使用該通道。 [這似乎工作](https://github.com/ozten/learning_rust/commit/c002cc6881dd8bf3d39f653e6f52a7adcb987181)。 – Ozten

回答

1

我無法測試,但我猜的解決方案是將repo_child流進入slurp_repos ,即:

fn main() { 
    let (db_child, repo_child) = DuplexStream(); 
    do spawn { 
     slurp_repos(repo_child); 
    } 
} 

fn slurp_repos(chan: DuplexStream<~str, ~str>) { 
    ... 
    do request.begin |event| { 
     ... 
     chan.send(api_url); 
    } 
} 

通過移動整個端點,它允許跨任務傳輸(因爲DuplexStream的能力是Send)。另外,請注意,共享(使用引用允許的)基本雙向流的終端(這是什麼DuplexStream)沒有意義:電話每端只能有一個人。

錯誤消息有關repo_child不活足夠長的時間是因爲slurp_repos類型需要的東西是'static即持續程序的整個生命週期,但repo_child絕對不會:這是本地的一個功能。

編譯器告訴你將'static放在slurp_repos上的原因是,因爲唯一的Send能夠引用是這個生命週期中的一個。此限制是必需的,因爲您可以在借用任務完成之前完成擁有的任務,然後銷燬/取消分配引用,留下懸掛的指針;在圖中:

start program/call main 
    | 
    v 
allocate repo_child 
    | 
    v 
spawn -----------------> slurp_repos(chan = &repo_child) 
    |       | 
    v       v 
finish     do things with the chan reference to repo_child 
    |       | 
    v       v 
deallocate repo_child general work ... 
          | 
          v 
         do more things with chan: 
          oops, already freed; use-after-free bug