Exercise 07-09
authorGreg Burri <greg.burri@gmail.com>
Fri, 25 Oct 2024 19:50:10 +0000 (21:50 +0200)
committerGreg Burri <greg.burri@gmail.com>
Fri, 25 Oct 2024 19:50:10 +0000 (21:50 +0200)
Cargo.lock
exercises/07_threads/09_bounded/Cargo.toml
exercises/07_threads/09_bounded/src/lib.rs

index 0dc0878..8b3bb4a 100644 (file)
@@ -205,6 +205,7 @@ dependencies = [
 name = "bounded"
 version = "0.1.0"
 dependencies = [
+ "thiserror",
  "ticket_fields",
 ]
 
index 506d14a..9f1862c 100644 (file)
@@ -5,3 +5,4 @@ edition = "2021"
 
 [dependencies]
 ticket_fields = { path = "../../../helpers/ticket_fields" }
+thiserror = "1"
index e661e68..4eb9d31 100644 (file)
@@ -1,44 +1,62 @@
 // TODO: Convert the implementation to use bounded channels.
 use crate::data::{Ticket, TicketDraft};
 use crate::store::{TicketId, TicketStore};
-use std::sync::mpsc::{Receiver, Sender};
+use std::sync::mpsc::{sync_channel, Receiver, Sender, SyncSender};
 
 pub mod data;
 pub mod store;
 
 #[derive(Clone)]
 pub struct TicketStoreClient {
-    sender: todo!(),
+    sender: SyncSender<Command>,
 }
 
 impl TicketStoreClient {
-    pub fn insert(&self, draft: TicketDraft) -> Result<TicketId, todo!()> {
-        todo!()
+    pub fn insert(&self, draft: TicketDraft) -> Result<TicketId, OverloadedError> {
+        let (response_sender, response_receiver) = sync_channel(1);
+        self.sender
+            .send(Command::Insert {
+                draft,
+                response_channel: response_sender,
+            })
+            .map_err(|_| OverloadedError)?;
+        Ok(response_receiver.recv().unwrap())
     }
 
-    pub fn get(&self, id: TicketId) -> Result<Option<Ticket>, todo!()> {
-        todo!()
+    pub fn get(&self, id: TicketId) -> Result<Option<Ticket>, OverloadedError> {
+        let (response_sender, response_receiver) = sync_channel(1);
+        self.sender
+            .send(Command::Get {
+                id,
+                response_channel: response_sender,
+            })
+            .map_err(|_| OverloadedError)?;
+        Ok(response_receiver.recv().unwrap())
     }
 }
 
+#[derive(Debug, thiserror::Error)]
+#[error("The store is overloaded")]
+pub struct OverloadedError;
+
 pub fn launch(capacity: usize) -> TicketStoreClient {
-    todo!();
+    let (sender, receiver) = sync_channel(capacity);
     std::thread::spawn(move || server(receiver));
-    todo!()
+    TicketStoreClient { sender }
 }
 
 enum Command {
     Insert {
         draft: TicketDraft,
-        response_channel: todo!(),
+        response_channel: SyncSender<TicketId>,
     },
     Get {
         id: TicketId,
-        response_channel: todo!(),
+        response_channel: SyncSender<Option<Ticket>>,
     },
 }
 
-pub fn server(receiver: Receiver<Command>) {
+fn server(receiver: Receiver<Command>) {
     let mut store = TicketStore::new();
     loop {
         match receiver.recv() {
@@ -47,14 +65,14 @@ pub fn server(receiver: Receiver<Command>) {
                 response_channel,
             }) => {
                 let id = store.add_ticket(draft);
-                todo!()
+                response_channel.send(id).unwrap();
             }
             Ok(Command::Get {
                 id,
                 response_channel,
             }) => {
                 let ticket = store.get(id);
-                todo!()
+                response_channel.send(ticket.cloned()).unwrap();
             }
             Err(_) => {
                 // There are no more senders, so we can safely break