Created
February 18, 2019 14:48
-
-
Save alcides/272a73f77160da654f656d5bd5ec64e1 to your computer and use it in GitHub Desktop.
Rust MPSC solution for the petition challenge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A solution for the "Vasco Vasconcelos Petition challenge", using rust mpsc package. | |
Alcides Fonseca <[email protected]> | |
How to run: | |
rustc example.rs && ./example | |
*/ | |
use std::thread; | |
use std::sync::mpsc; | |
use std::sync::mpsc::{Sender, Receiver}; | |
use std::collections::LinkedList; | |
/* Unfortunately, unions cannot be clonable. Since channels are typed, I have used enums to fake enums. */ | |
enum RType { | |
Details, | |
Commit, | |
Sign, | |
Check | |
} | |
struct Request { | |
t: RType, | |
name: String, | |
text: String, | |
d : Description | |
} | |
struct Response { | |
ok: bool, | |
howmany: usize | |
} | |
struct Description { | |
is_a : bool, | |
a: usize, | |
b : Sender<Response> | |
} | |
struct Connection { | |
writer: Sender<Response>, | |
reader: Receiver<Request> | |
} | |
#[derive(Debug)] | |
struct Petition { | |
name: String, | |
text: String, | |
support: LinkedList<String> | |
} | |
fn server(server_r:Receiver<Connection>) { | |
for conn in server_r { | |
thread::spawn(move || { | |
println!("New connection"); | |
server_thread(conn); | |
}); | |
} | |
} | |
fn server_thread(c:Connection) { | |
let mut p = Petition { | |
name: String::from("Default name"), | |
text: String::from("Default text"), | |
support: LinkedList::new() | |
}; | |
for req in c.reader { | |
match req.t { | |
RType::Details => { | |
p.name = req.name; | |
p.text = req.text; | |
println!("{:?}", p); | |
}, | |
RType::Commit => { | |
c.writer.send(Response{ | |
ok: p.name != "F word", | |
howmany: 0 | |
}).unwrap(); | |
} | |
RType::Sign => { | |
p.support.push_back(req.name) | |
}, | |
RType::Check => { | |
c.writer.send(Response{ | |
ok: p.name != "F word", | |
howmany: p.support.len() | |
}).unwrap(); | |
}, | |
} | |
} | |
} | |
// fn bad_client(server_w:Sender<Connection>) { | |
// let (c_to_s_writer, c_to_s_reader) = mpsc::channel(); | |
// let (s_to_c_writer, s_to_c_reader) = mpsc::channel(); | |
// | |
// let conn = Connection { writer:s_to_c_writer, reader:c_to_s_reader }; | |
// | |
// server_w.send(conn).unwrap(); | |
// c_to_s_writer.send(Request { | |
// t: RType::Details, | |
// name: String::from("F word"), | |
// text: String::from("Wolf is good"), | |
// d: Description { a: 1 } | |
// }).unwrap(); | |
// | |
// c_to_s_writer.send(Request { | |
// t: RType::Commit, | |
// name: String::from(""), | |
// text: String::from(""), | |
// d: Description { a: 1 } | |
// }).unwrap(); | |
// | |
// let resp = s_to_c_reader.recv().unwrap(); | |
// if resp.ok { println!("accepted"); } else { println!("rejected"); } | |
// | |
// } | |
// | |
// fn client(server_w:Sender<Connection>) { | |
// let (c_to_s_writer, c_to_s_reader) = mpsc::channel(); | |
// let (s_to_c_writer, s_to_c_reader) = mpsc::channel(); | |
// | |
// let conn = Connection { writer:s_to_c_writer, reader:c_to_s_reader }; | |
// | |
// server_w.send(conn).unwrap(); | |
// | |
// c_to_s_writer.send(Request{ | |
// t: RType::Details, | |
// name: String::from("Save the wolf!"), | |
// text: String::from("Wolf is good") | |
// }).unwrap(); | |
// | |
// c_to_s_writer.send(Request{ | |
// t: RType::Details, | |
// name: String::from("Save the good wolf!"), | |
// text: String::from("Wolf is awesome") | |
// }).unwrap(); | |
// | |
// c_to_s_writer.send(Request { | |
// t: RType::Commit, | |
// name: String::from(""), | |
// text: String::from("") | |
// }).unwrap(); | |
// | |
// let resp = s_to_c_reader.recv().unwrap(); | |
// if resp.ok { println!("accepted"); } else { println!("rejected"); } | |
// | |
// | |
// c_to_s_writer.send(Request{ | |
// t: RType::Sign, | |
// name: String::from("Vasco"), | |
// text: String::from("") | |
// }).unwrap(); | |
// | |
// c_to_s_writer.send(Request{ | |
// t: RType::Sign, | |
// name: String::from("Alcides"), | |
// text: String::from("") | |
// }).unwrap(); | |
// | |
// c_to_s_writer.send(Request{ | |
// t: RType::Check, | |
// name: String::from(""), | |
// text: String::from("") | |
// }).unwrap(); | |
// | |
// let resp = s_to_c_reader.recv().unwrap(); | |
// println!("Got {:?} signature(s)", resp.howmany); | |
// } | |
// | |
fn great_client(server_w:Sender<Connection>) { | |
let (c_to_s_writer, c_to_s_reader) = mpsc::channel(); | |
let (s_to_c_writer, s_to_c_reader) = mpsc::channel(); | |
let conn = Connection { writer:s_to_c_writer, reader:c_to_s_reader }; | |
server_w.send(conn).unwrap(); | |
c_to_s_writer.send(Request{ | |
t: RType::Details, | |
name: String::from("Save the Portuguese donkey!"), | |
text: String::from("Donkeys are useful!"), | |
d: Description { a: 1 } | |
}).unwrap(); | |
c_to_s_writer.send(Request { | |
t: RType::Commit, | |
name: String::from(""), | |
text: String::from(""), | |
d: Description { a: 1 } | |
}).unwrap(); | |
let resp = s_to_c_reader.recv().unwrap(); | |
if resp.ok { println!("accepted"); } else { println!("rejected"); } | |
let c_to_s_writer_alt = Sender::clone(&c_to_s_writer); | |
thread::spawn(move || { | |
c_to_s_writer_alt.send(Request{ | |
t: RType::Sign, | |
name: String::from("Vasco"), | |
text: String::from(""), | |
d: Description { a: 1 } | |
}).unwrap(); | |
}); | |
let c_to_s_writer_alt = Sender::clone(&c_to_s_writer); | |
thread::spawn(move || { | |
c_to_s_writer_alt.send(Request{ | |
t: RType::Sign, | |
name: String::from("Alcides"), | |
text: String::from(""), | |
d: Description { a: 1 } | |
}).unwrap(); | |
}); | |
c_to_s_writer.send(Request{ | |
t: RType::Check, | |
name: String::from(""), | |
text: String::from(""), | |
d: Description { a: 1 } | |
}).unwrap(); | |
let resp = s_to_c_reader.recv().unwrap(); | |
println!("Got {:?} signature(s)", resp.howmany); | |
} | |
fn main() { | |
let (server_w, server_r):(Sender<Connection>, Receiver<Connection>) = mpsc::channel(); | |
// let server_ws = Sender::clone(&server_w); | |
// thread::spawn(move || { | |
// bad_client(server_ws); | |
// }); | |
//let server_ws = Sender::clone(&server_w); | |
//thread::spawn(move || { | |
// client(server_ws); | |
//}); | |
let server_ws = Sender::clone(&server_w); | |
thread::spawn(move || { | |
great_client(server_ws); | |
}); | |
server(server_r); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment