2017-07-25 4 views
0

Ich schreibe eine Phoenix-Client-Bibliothek für Rust und nutze den asynchronen Websocket-Client von rust-websockets. Im Moment habe ich Probleme herauszufinden, wie man Callback-Funktionen an den Thread weiterleitet, der den Websocket-Verkehr verarbeitet. Ich habe eine vereinfachte Struktur:Aufruf eines FnMut-Callbacks von einem anderen Thread

pub struct Socket { 
    endpoint:    String, 
    connected:    Arc<AtomicBool>, 
    state_change_close:  Option<Box<FnMut(String)>>, 
} 

Diese Struktur hat eine connect Funktion wie folgt angelegt:

pub fn connect(&mut self) -> Result<(), String> { 
    if self.connected.load(Ordering::Relaxed) { 
     return Ok(()) 
    } 

    // Copy endpoint string, otherwise we get an error on thread::spawn 
    let connection_string = self.endpoint.clone(); 
    let (usr_msg, stdin_ch) = mpsc::channel(0); 

    let connection_thread = thread::spawn(move || { 
     // tokio core for running event loop 
     let mut core = Core::new().unwrap(); 
     let runner = ClientBuilder::new(&connection_string) 
      .unwrap() 
      .add_protocol("rust-websocket") 
      .async_connect_insecure(&core.handle()) 
      .and_then(|(duplex, _)| { 
       let (sink, stream) = duplex.split(); 
       stream.filter_map(|message| { 
        println!("Received Message: {:?}", message); 
        match message { 
         OwnedMessage::Close(e) => { 
          // This is the line where I am trying to call the callback 
          if let Some(ref mut func) = self.state_change_close { 
           (func)(e.unwrap().reason); 
          } 
          Some(OwnedMessage::Close(e)) 
         }, 
         _ => None, 
        } 
       }) 
       .select(stdin_ch.map_err(|_| WebSocketError::NoDataAvailable)) 
       .forward(sink) 
      }); 

     // Start the event loop 
     core.run(runner).unwrap(); 
    }); 
    self.connected.store(true, Ordering::Relaxed); 
    return Ok(()) 
} 

Wenn ich versuche, diesen Code zu kompilieren ich die folgende Fehlermeldung erhalten:

error[E0277]: the trait bound `std::ops::FnMut(std::string::String) + 'static: std::marker::Send` is not satisfied 
    --> src\socket.rs:99:29 
    | 
99 |  let connection_thread = thread::spawn(move || { 
    |        ^^^^^^^^^^^^^ the trait `std::marker::Send` is not implemented for `std::ops::FnMut(std::string::String) + 'static` 
    | 

Ich habe versucht, den Typ state_change_close zu einem Mutex<Option<...>> zu ändern, um Threadsicherheitsprobleme zu vermeiden, aber das half nicht mit diesem Problem. Ist das, was ich versuche, möglich?

Antwort

1

Nach einigen weiteren Recherchen erkannte ich, dass ich nur ändern musste Option<Box<FnMut(String)>> zu Option<Box<FnMut(String) + Send>> und kopieren Sie das um meinen Code zu überall, dass der Rückruf festgelegt werden könnte. Erfahren Sie mehr über Merkmalsobjekte!

Verwandte Themen