Bienvenidos sean a este post, hoy veremos que pasa entre los canales y la propiedad.
En el post anterior hablamos sobre los canales y como nos ayuda a enviar informacion entre distintos threads, en este post hablamos sobre que es la propiedad (ownership) en una variable pero estos dos trabajan juntos para evitar inconvenientes a la hora de trabajar con nuestros codigos, tomemos el proyecto que creamos en el post anterior y modifiquemos el codigo de main.rs de la siguiente manera:
Nota: Si no lo poseen generen un nuevo proyecto llamado canal.
main.rs
use std::thread;
use std::sync::mpsc;
fn main()
{
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let v = String::from("Hola");
tx.send(v).unwrap();
println!("V: {}", v);
});
let recibido = rx.recv().unwrap();
println!("Recibido: {}", recibido);
}
Sin entrar en muchos detalles, este codigo genera un nuevo thread el cual transmite un String de este nuevo thread al principal y el otro lo recibe, para mas detalle les recomiendo el post anterior, en este caso lo unico diferente fue agregar un println para mostrar el valor de la variable v, compilemos y veamos que sucede:
tinchicus@dbn001vrt:~/lenguajes/rust/canal$ cargo build
Compiling canal v0.1.0 (/home/tinchicus/lenguajes/rust/canal)
error[E0382]: borrow of moved value: `v`
--> src/main.rs:11:21
|
9 | let v = String::from("Hola");
| - move occurs because `v` has type `String`, which does not implement the `Copy` trait
10 | tx.send(v).unwrap();
| - value moved here
11 | println!("V: {}", v);
| ^ value borrowed here after move
For more information about this error, try `rustc --explain E0382`.
error: could not compile `canal` due to previous error
tinchicus@dbn001vrt:~/lenguajes/rust/canal$
Como pueden ver no se pudo compilar porque al momento de querer mostrar el valor de la variable ya la enviamos al otro thread y no sabemos si en el destino no fue modificada, recuerden que los tipos primitivos manejan el Copy trait y estos tipos no, y principalmente este se ve afectada porque el metodo send es el encargado de tomar propiedad (ownership) sobre la informacion que estamos enviando, y esto evitara cualquier tipo de inconsistencia como comentamos anteriormente, recuerden que este lenguaje es memory-safe tal como mencionamos en este post, con todo esto comentado como podriamos solucionarlo? De una manera sencilla, para ello tomaremos este bloque:
thread::spawn(move || {
let v = String::from("Hola");
tx.send(v).unwrap();
println!("V: {}", v);
});
Y lo cambiaremos de la siguiente manera:
thread::spawn(move || {
let v = String::from("Hola");
println!("V: {}", v);
tx.send(v).unwrap();
});
Lo que hacemos es simplemente mostrar el mensaje antes de que le cambiemos la propiedad para que el compilador sepa perfectamente como se maneja la informacion, compilemos y veamos su salida:
tinchicus@dbn001vrt:~/lenguajes/rust/canal$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.03s
Running `target/debug/canal`
V: Hola
Recibido: Hola
tinchicus@dbn001vrt:~/lenguajes/rust/canal$
En resumen, hoy hemos visto un problema potencial que podemos tener entre los canales y la propiedad (ownership), como uno puede afectar al otro sin que nos demos cuenta, y tambien hemos visto como solucionarlo, espero les haya sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.


Donación
Es para mantenimento del sitio, gracias!
$1.50
