2015-01-18 2 views
2

Я хотел был бы послать команды (затворы) к различным потокам, с закрытием захвата non-Sync переменной (поэтому я не могу «поделить» замыкание с дугой, как объяснено в Can you clone a closure?).Как я могу клонировать закрытие?

Закрытие только захватывает элементы, которые реализуют Clone, поэтому я чувствовал бы, что замыкание может быть получено также Clone.

use std::thread::Thread; 
use std::sync::{mpsc, Arc}; 
use std::sync::mpsc::Sender; 
use std::thunk::Invoke; 
type Command = Box<for <'a> Invoke<&'a mut SenderWrapper,()> + Send>; 

struct SenderWrapper { 
    tx: Option<Sender<u64>>, 
} 
impl SenderWrapper { 
    fn new() -> SenderWrapper { 
     SenderWrapper{tx: None} 
    } 
} 

fn main() { 
    let (responses_tx,responses_rx) = mpsc::channel(); 
    let closure = Box::new(move |:snd: &mut SenderWrapper| { 
     snd.tx = Some(responses_tx); // Captures tx, which is not Sync but is Clone 
    }); 

    let mut commands = Vec::new(); 
    for i in range(0,2i32) { 
     let (commands_tx,commands_rx) = mpsc::channel(); 
     commands.push(commands_tx); 
     Thread::spawn(move || { 
      let mut wrapper = SenderWrapper::new(); 
      let command: Command = commands_rx.recv().unwrap(); 
      command.invoke(&mut wrapper); 
      // Continue ... 
     }); 
    } 

    for tx in commands.iter() { 
     commands[0].send(closure.clone()).unwrap(); // How can I make this clone() work? 
    } 
    // use answers ... 
} 

Есть ли какой-либо способ в текущем синтаксисе, где мы можем реализовать/получить черты для замыканий?

ПРИМЕЧАНИЕ: грязным обходным путем для этого было бы определить вручную структуру, содержащую требуемую среду, реализовать Clone и определить свойство FnOnce или Invoke.

ответ

2

Это не отвечает на ваш прямой вопрос, но возможно ли просто клонировать ваши переменные, прежде чем захватывать их в закрытии?

for tx in commands.iter() { 
    let my_resp_tx = responses_tx.clone(); 
    let closure = Box::new(move |:snd: &mut SenderWrapper| { 
     snd.tx = Some(my_resp_tx); 
    }); 
    commands[0].send(closure).unwrap(); 
} 
+2

В простом примере, который я предусмотрел, это было бы действительно возможно. Однако, в моем реальном варианте использования, команда поступает из другой части кода, которая не должна знать, сколько раз клонирование будет клонировано. – Vaelden

+0

Вы могли бы извлечь генерацию замыкания в функцию и затем вызвать эту функцию для каждой задачи? – Shepmaster

+1

Да, на самом деле это должно быть возможно сделать функцию или закрытие, которое было бы фабрикой «отходящего закрытия». Спасибо за идею! Жаль, что мы не можем клонировать() закрытие напрямую, хотя ... – Vaelden

Смежные вопросы