Skip to content

Instantly share code, notes, and snippets.

@alcides
Created February 18, 2019 14:48
Show Gist options
  • Save alcides/272a73f77160da654f656d5bd5ec64e1 to your computer and use it in GitHub Desktop.
Save alcides/272a73f77160da654f656d5bd5ec64e1 to your computer and use it in GitHub Desktop.
Rust MPSC solution for the petition challenge
/*
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