2016-03-02 60 views
1

我試圖使用協程作爲學習練習(而不是作業)來實現Rust中的Eratosthenes篩,我找不到任何合理的方式將每個線程連接到兩個不同通道的末端ReceiverSender如何在Rust中使用通道菊花鏈線程?

Receiver涉及兩個不同的任務,即報告迄今爲止發現的最高素數,併爲濾波器提供更多候選素數。這是算法的基礎。

這是我想要做的,但不能,因爲Receiver不能在線程之間轉移。毫無疑問,使用std::sync::Arc似乎沒有幫助。

請注意,我不明白爲什麼這不起作用

fn main() { 
    let (basetx, baserx): (Sender<u32>, Receiver<u32>) = channel(); 
    let max_number = 103; 
    thread::spawn(move|| { 
     generate_natural_numbers(&basetx, max_number); 
    }); 
    let oldrx = &baserx; 
    loop { 
     // we need the prime in this thread 
     let prime = match oldrx.recv() { 
      Ok(num) => num, 
      Err(_) => { break; 0 } 
     }; 
     println!("{}",prime); 
     // create (newtx, newrx) in a deliberately unspecified way 
     // now we need to pass the receiver off to the sieve thread 
     thread::spawn(move || { 
      sieve(oldrx, newtx, prime); // forwards numbers if not divisible by prime 
     }); 
     oldrx = newrx; 
    } 
} 

等效工作Go代碼:

func main() { 
     channel := make(chan int) 
     var ok bool = true; 
     var prime int = 0; 
     go generate(channel, 103) 
     for true { 
       prime, ok = <- channel 
       if !ok { 
         break; 
       } 
       new_channel := make(chan int) 
       go sieve(channel, new, prime) 
       channel = new_channel 
       fmt.Println(prime) 
     } 
} 

什麼是對付這樣一個地方情況的最好辦法Receiver需要切換到不同的線程?

回答

3

你真的不解釋,你有什麼問題,但你的代碼是非常接近:

use std::sync::mpsc::{channel, Sender, Receiver}; 
use std::thread; 

fn generate_numbers(tx: Sender<u8>) { 
    for i in 2..100 { 
     tx.send(i).unwrap(); 
    } 
} 

fn filter(rx: Receiver<u8>, tx: Sender<u8>, val: u8) { 
    for v in rx { 
     if v % val != 0 { 
      tx.send(v).unwrap(); 
     } 
    } 
} 

fn main() { 
    let (base_tx, base_rx) = channel(); 
    thread::spawn(move || { 
     generate_numbers(base_tx); 
    }); 

    let mut old_rx = base_rx; 

    loop { 
     let num = match old_rx.recv() { 
      Ok(v) => v, 
      Err(_) => break, 
     }; 

     println!("prime: {}", num); 

     let (new_tx, new_rx) = channel(); 

     thread::spawn(move || { 
      filter(old_rx, new_tx, num); 
     }); 

     old_rx = new_rx; 
    } 
} 

使用協同程序

危險,危險,威爾魯濱遜!這些是而不是協程;他們是完整的線程!與協同程序相比,這些重量更重。

什麼是最好的方式來處理這種情況下,Receiver需要切換到不同的線程?

只是...將Receiver的所有權轉讓給線程?