2016-03-09 32 views
8

Khi tôi spawn một chuỗi trong Rust, tôi nhận được một JoinHandle, đó là tốt cho ... tham gia (một hoạt động chặn), và không nhiều khác. Làm cách nào để kiểm tra xem một chuỗi con đã thoát (tức là, JoinHandle.join() sẽ không chặn) khỏi chuỗi chính không? Điểm thưởng nếu bạn biết cách giết một chuỗi con.Làm thế nào để kiểm tra xem một sợi đã hoàn thành trong Rust chưa?

Tôi tưởng tượng bạn có thể làm điều này bằng cách tạo kênh, gửi nội dung nào đó cho trẻ và bắt lỗi, nhưng điều đó có vẻ như không cần thiết phức tạp và chi phí.

Trả lời

8

Kể từ Rust 1.7, không có API trong thư viện chuẩn để kiểm tra xem một chuỗi con đã thoát mà không chặn.

Giải pháp thay thế di động sẽ là sử dụng channels để gửi thư từ trẻ đến cha mẹ để báo hiệu rằng đứa trẻ sắp thoát. Receiver có phương pháp không chặn try_recv. Khi try_recv không nhận được tin nhắn, bạn có thể sử dụng join() trên JoinHandle để truy xuất kết quả của chuỗi.

Ngoài ra còn có các đặc điểm mở rộng dành riêng cho nền tảng không ổn định cho phép bạn có được trình xử lý chỉ thô. Sau đó, bạn sẽ phải viết mã nền tảng cụ thể để kiểm tra xem luồng có thoát hay không.

Nếu bạn cho rằng tính năng này phải ở trong thư viện chuẩn của Rust, bạn có thể submit an RFC (hãy nhớ đọc README trước!).

Điểm thưởng nếu bạn biết cách tiêu diệt một chuỗi con.

Chủ đề trong Rust được triển khai bằng các chuỗi hệ điều hành gốc. Mặc dù hệ điều hành có thể cung cấp một cách để tiêu diệt một sợi, đó là một ý tưởng tồi để làm như vậy, vì các tài nguyên mà luồng được phân bổ sẽ không được dọn sạch cho đến khi kết thúc .

8

Câu trả lời ngắn gọn là không thể. Nhưng đây không phải là điểm thực sự cần giải quyết.

Điểm thưởng nếu bạn biết cách tiêu diệt một chuỗi con.

KHÔNG BAO GIỜ

Ngay cả trong ngôn ngữ mà ủng hộ chủ đề giết chết (see Java here), nó được khuyến khích không.

thực hiện của một chủ đề thường được mã hóa với rõ ràng điểm tương tác, và thường có giả định ngầm rằng không có sự gián đoạn khác sẽ xảy ra.

Ví dụ nghiêm trọng nhất là tài nguyên khóa học: phương pháp "giết" ngây thơ sẽ dừng thực thi chuỗi; điều này có nghĩa là không phát hành bất kỳ tài nguyên nào. Bạn có thể nghĩ về trí nhớ, ít nhất là lo lắng của bạn. Hãy tưởng tượng, thay vào đó, tất cả các Mutex mà không được mở khóa và sẽ tạo ra deadlocks sau này ...

Tùy chọn khác sẽ là tiêm panic trong chủ đề, điều này sẽ gây khó chịu. Tuy nhiên, bạn không thể chỉ bắt đầu thư giãn tại bất kỳ thời điểm nào!Chương trình sẽ phải xác định điểm an toàn mà tại đó việc tiêm panic sẽ được đảm bảo an toàn (việc tiêm nó vào bất kỳ điểm nào khác có nghĩa là có khả năng làm hỏng các đối tượng dùng chung); làm thế nào để xác định các điểm an toàn như vậy và tiêm panic có một vấn đề nghiên cứu mở bằng ngôn ngữ bản địa, đặc biệt là các vấn đề được thực thi trên các hệ thống W^X (nơi các trang bộ nhớ có thể ghi được hoặc không thể thực thi được).

Tóm lại, không có cách nào được biết một cách an toàn (cả trí nhớ và khôn ngoan về chức năng) sẽ xóa một chuỗi.

2

Có thể, bạn bè. Sử dụng số điện thoại số lượt truy cập mà Rust sẽ giảm trên kết thúc hoặc hoảng loạn. 100% an toàn. Ví dụ:

use std::time::Duration; 
use std::sync::Arc; 
use std::sync::atomic::{AtomicBool, Ordering}; 
use std::thread; 

fn main() { 
    // Play with this flag 
    let fatal_flag = true; 
    let do_stop = true; 

    let working = Arc::new(AtomicBool::new(true)); 
    let control = Arc::downgrade(&working); 

    thread::spawn(move || { 
     while (*working).load(Ordering::Relaxed) { 
      if fatal_flag { 
       panic!("Oh, my God!"); 
      } else { 
       thread::sleep(Duration::from_millis(20)); 
       println!("I'm alive!"); 
      } 
     } 
    }); 

    thread::sleep(Duration::from_millis(50)); 

    // To stop thread 
    if do_stop { 
     match control.upgrade() { 
      Some(working) => (*working).store(false, Ordering::Relaxed), 
      None => println!("Sorry, but thread died already."), 
     } 
    } 

    thread::sleep(Duration::from_millis(50)); 

    // To check it's alive/died 
    match control.upgrade() { 
     Some(_) => println!("Thread alive!"), 
     None => println!("Thread ends!"), 
    } 
} 

Gist: https://gist.github.com/DenisKolodin/edea80f2f5becb86f718c330219178e2

Tại sân chơi: https://play.rust-lang.org/?gist=9a0cf161ba0bbffe3824b9db4308e1fb&version=stable&backtrace=0

UPD: Tôi đã tạo thread-control thùng mà thực hiện phương pháp này: https://github.com/DenisKolodin/thread-control

Các vấn đề liên quan