Compare commits
2 Commits
9bc063a05b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b044878fe8 | |||
| 4fbee2d894 |
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -205,6 +205,7 @@ dependencies = [
|
|||||||
name = "bounded"
|
name = "bounded"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
"ticket_fields",
|
"ticket_fields",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn intro() -> &'static str {
|
fn intro() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to _!"
|
"I'm ready to build a concurrent ticket management system!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -15,7 +15,14 @@
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
pub fn sum(v: Vec<i32>) -> i32 {
|
pub fn sum(v: Vec<i32>) -> i32 {
|
||||||
todo!()
|
// let mut c1 = (v.clone()[..v.len() / 2]).iter().collect::<Vec<_>>();
|
||||||
|
// let mut c2 = (v.clone()[v.len() / 2..]).iter().collect::<Vec<_>>();
|
||||||
|
let (c1, c2) = v.split_at(v.len() / 2);
|
||||||
|
let c1 = c1.to_vec();
|
||||||
|
let c2 = c2.to_vec();
|
||||||
|
let t1 = std::thread::spawn(move || c1.iter().sum::<i32>());
|
||||||
|
let t2 = std::thread::spawn(move || c2.iter().sum::<i32>());
|
||||||
|
t1.join().unwrap() + t2.join().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
pub fn sum(slice: &'static [i32]) -> i32 {
|
pub fn sum(slice: &'static [i32]) -> i32 {
|
||||||
todo!()
|
let (s1, s2) = slice.split_at(slice.len() / 2);
|
||||||
|
let t1 = std::thread::spawn(|| s1.iter().sum::<i32>());
|
||||||
|
let t2 = std::thread::spawn(|| s2.iter().sum::<i32>());
|
||||||
|
t1.join().unwrap() + t2.join().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -6,7 +6,11 @@
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
pub fn sum(v: Vec<i32>) -> i32 {
|
pub fn sum(v: Vec<i32>) -> i32 {
|
||||||
todo!()
|
let lv = v.leak();
|
||||||
|
let (s1, s2) = lv.split_at(lv.len() / 2);
|
||||||
|
let t1 = std::thread::spawn(|| s1.iter().sum::<i32>());
|
||||||
|
let t2 = std::thread::spawn(|| s2.iter().sum::<i32>());
|
||||||
|
return t1.join().unwrap() + t2.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
// Don't perform any heap allocation. Don't leak any memory.
|
// Don't perform any heap allocation. Don't leak any memory.
|
||||||
|
|
||||||
pub fn sum(v: Vec<i32>) -> i32 {
|
pub fn sum(v: Vec<i32>) -> i32 {
|
||||||
todo!()
|
let mid = v.len() / 2;
|
||||||
|
let (s1, s2) = v.split_at(mid);
|
||||||
|
std::thread::scope(|scope| {
|
||||||
|
let t1 = scope.spawn(|| s1.iter().sum::<i32>());
|
||||||
|
let t2 = scope.spawn(|| s2.iter().sum::<i32>());
|
||||||
|
t1.join().unwrap() + t2.join().unwrap()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
|
|
||||||
|
use data::TicketDraft;
|
||||||
|
use store::TicketStore;
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
|
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Insert(todo!()),
|
Insert(TicketDraft),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the system by spawning the server thread.
|
// Start the system by spawning the server thread.
|
||||||
@@ -20,4 +23,14 @@ pub fn launch() -> Sender<Command> {
|
|||||||
// Enter a loop: wait for a command to show up in
|
// Enter a loop: wait for a command to show up in
|
||||||
// the channel, then execute it, then start waiting
|
// the channel, then execute it, then start waiting
|
||||||
// for the next command.
|
// for the next command.
|
||||||
pub fn server(receiver: Receiver<Command>) {}
|
pub fn server(receiver: Receiver<Command>) {
|
||||||
|
let mut tickStor = TicketStore::new();
|
||||||
|
'aLoop: loop {
|
||||||
|
let command = receiver.recv().ok().unwrap();
|
||||||
|
match command {
|
||||||
|
Command::Insert(a) => {
|
||||||
|
tickStor.add_ticket(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ fn ready() {
|
|||||||
// since our server doesn't expose any **read** actions.
|
// since our server doesn't expose any **read** actions.
|
||||||
// We have no way to know if the inserts are actually happening and if they
|
// We have no way to know if the inserts are actually happening and if they
|
||||||
// are happening correctly.
|
// are happening correctly.
|
||||||
let move_forward = false;
|
let move_forward = true;
|
||||||
|
|
||||||
assert!(move_forward);
|
assert!(move_forward);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
pub struct DropTracker<T> {
|
pub struct DropTracker<T> {
|
||||||
value: T,
|
value: T,
|
||||||
counter: todo!(),
|
counter: Rc<RefCell<usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DropTracker<T> {
|
impl<T> DropTracker<T> {
|
||||||
pub fn new(value: T, counter: todo!()) -> Self {
|
pub fn new(value: T, counter: Rc<RefCell<usize>>) -> Self {
|
||||||
Self { value, counter }
|
Self { value, counter }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Drop for DropTracker<T> {
|
impl<T> Drop for DropTracker<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
todo!()
|
*self.counter.borrow_mut() += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
|
use data::{Ticket, TicketDraft};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
|
use store::TicketId;
|
||||||
|
|
||||||
use crate::store::TicketStore;
|
use crate::store::TicketStore;
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
@@ -6,8 +9,14 @@ pub mod store;
|
|||||||
|
|
||||||
// Refer to the tests to understand the expected schema.
|
// Refer to the tests to understand the expected schema.
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Insert { todo!() },
|
Insert {
|
||||||
Get { todo!() }
|
draft: TicketDraft,
|
||||||
|
response_sender: Sender<TicketId>,
|
||||||
|
},
|
||||||
|
Get {
|
||||||
|
id: TicketId,
|
||||||
|
response_sender: Sender<Option<Ticket>>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn launch() -> Sender<Command> {
|
pub fn launch() -> Sender<Command> {
|
||||||
@@ -21,19 +30,25 @@ pub fn server(receiver: Receiver<Command>) {
|
|||||||
let mut store = TicketStore::new();
|
let mut store = TicketStore::new();
|
||||||
loop {
|
loop {
|
||||||
match receiver.recv() {
|
match receiver.recv() {
|
||||||
Ok(Command::Insert {}) => {
|
Ok(Command::Insert {
|
||||||
todo!()
|
draft,
|
||||||
|
response_sender,
|
||||||
|
}) => {
|
||||||
|
let id = store.add_ticket(draft);
|
||||||
|
response_sender.send(id);
|
||||||
}
|
}
|
||||||
Ok(Command::Get {
|
Ok(Command::Get {
|
||||||
todo!()
|
id,
|
||||||
|
response_sender,
|
||||||
}) => {
|
}) => {
|
||||||
todo!()
|
let tick = store.get(id);
|
||||||
|
response_sender.send(tick.cloned());
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// There are no more senders, so we can safely break
|
// There are no more senders, so we can safely break
|
||||||
// and shut down the server.
|
// and shut down the server.
|
||||||
break
|
break;
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,23 +7,38 @@ pub mod store;
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
// TODO: flesh out the client implementation.
|
// TODO: flesh out the client implementation.
|
||||||
pub struct TicketStoreClient {}
|
pub struct TicketStoreClient {
|
||||||
|
sender: Sender<Command>,
|
||||||
|
}
|
||||||
|
|
||||||
impl TicketStoreClient {
|
impl TicketStoreClient {
|
||||||
// Feel free to panic on all errors, for simplicity.
|
// Feel free to panic on all errors, for simplicity.
|
||||||
pub fn insert(&self, draft: TicketDraft) -> TicketId {
|
pub fn insert(&self, draft: TicketDraft) -> TicketId {
|
||||||
todo!()
|
let (sendr, recvr) = std::sync::mpsc::channel::<TicketId>();
|
||||||
|
match self.sender.send(Command::Insert {
|
||||||
|
draft: draft,
|
||||||
|
response_channel: sendr,
|
||||||
|
}) {
|
||||||
|
Ok(a) => {}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
recvr.recv().ok().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: TicketId) -> Option<Ticket> {
|
pub fn get(&self, id: TicketId) -> Option<Ticket> {
|
||||||
todo!()
|
let (sendr, recvr) = std::sync::mpsc::channel::<Option<Ticket>>();
|
||||||
|
self.sender.send(Command::Get {
|
||||||
|
id: id,
|
||||||
|
response_channel: sendr,
|
||||||
|
});
|
||||||
|
recvr.recv().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn launch() -> TicketStoreClient {
|
pub fn launch() -> TicketStoreClient {
|
||||||
let (sender, receiver) = std::sync::mpsc::channel();
|
let (sender, receiver) = std::sync::mpsc::channel();
|
||||||
std::thread::spawn(move || server(receiver));
|
std::thread::spawn(move || server(receiver));
|
||||||
todo!()
|
TicketStoreClient { sender }
|
||||||
}
|
}
|
||||||
|
|
||||||
// No longer public! This becomes an internal detail of the library now.
|
// No longer public! This becomes an internal detail of the library now.
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
||||||
|
thiserror="* "
|
||||||
|
|||||||
@@ -1,40 +1,58 @@
|
|||||||
// TODO: Convert the implementation to use bounded channels.
|
// TODO: Convert the implementation to use bounded channels.
|
||||||
use crate::data::{Ticket, TicketDraft};
|
use crate::data::{Ticket, TicketDraft};
|
||||||
use crate::store::{TicketId, TicketStore};
|
use crate::store::{TicketId, TicketStore};
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender, SyncSender};
|
||||||
|
|
||||||
pub mod data;
|
pub mod data;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TicketStoreClient {
|
pub struct TicketStoreClient {
|
||||||
sender: todo!(),
|
sender: SyncSender<Command>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[error("Server is overloaded")]
|
||||||
|
pub struct OverLoadedError;
|
||||||
|
|
||||||
impl TicketStoreClient {
|
impl TicketStoreClient {
|
||||||
pub fn insert(&self, draft: TicketDraft) -> Result<TicketId, todo!()> {
|
pub fn insert(&self, draft: TicketDraft) -> Result<TicketId, OverLoadedError> {
|
||||||
todo!()
|
let (sender, receiver) = std::sync::mpsc::sync_channel(1);
|
||||||
|
self.sender
|
||||||
|
.try_send(Command::Insert {
|
||||||
|
draft,
|
||||||
|
response_channel: sender,
|
||||||
|
})
|
||||||
|
.map_err(|_| OverLoadedError);
|
||||||
|
Ok(receiver.recv().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: TicketId) -> Result<Option<Ticket>, todo!()> {
|
pub fn get(&self, id: TicketId) -> Result<Option<Ticket>, OverLoadedError> {
|
||||||
todo!()
|
let (sender, receiver) = std::sync::mpsc::sync_channel(1);
|
||||||
|
self.sender
|
||||||
|
.try_send(Command::Get {
|
||||||
|
id,
|
||||||
|
response_channel: sender,
|
||||||
|
})
|
||||||
|
.map_err(|_| OverLoadedError);
|
||||||
|
Ok(receiver.recv().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn launch(capacity: usize) -> TicketStoreClient {
|
pub fn launch(capacity: usize) -> TicketStoreClient {
|
||||||
todo!();
|
let (sender, receiver) = std::sync::mpsc::sync_channel(capacity);
|
||||||
std::thread::spawn(move || server(receiver));
|
std::thread::spawn(move || server(receiver));
|
||||||
todo!()
|
TicketStoreClient { sender }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Command {
|
enum Command {
|
||||||
Insert {
|
Insert {
|
||||||
draft: TicketDraft,
|
draft: TicketDraft,
|
||||||
response_channel: todo!(),
|
response_channel: SyncSender<TicketId>,
|
||||||
},
|
},
|
||||||
Get {
|
Get {
|
||||||
id: TicketId,
|
id: TicketId,
|
||||||
response_channel: todo!(),
|
response_channel: SyncSender<Option<Ticket>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,14 +65,14 @@ pub fn server(receiver: Receiver<Command>) {
|
|||||||
response_channel,
|
response_channel,
|
||||||
}) => {
|
}) => {
|
||||||
let id = store.add_ticket(draft);
|
let id = store.add_ticket(draft);
|
||||||
todo!()
|
response_channel.send(id);
|
||||||
}
|
}
|
||||||
Ok(Command::Get {
|
Ok(Command::Get {
|
||||||
id,
|
id,
|
||||||
response_channel,
|
response_channel,
|
||||||
}) => {
|
}) => {
|
||||||
let ticket = store.get(id);
|
let ticket = store.get(id);
|
||||||
todo!()
|
response_channel.send(ticket.cloned());
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// There are no more senders, so we can safely break
|
// There are no more senders, so we can safely break
|
||||||
|
|||||||
@@ -35,7 +35,15 @@ impl TicketStoreClient {
|
|||||||
Ok(response_receiver.recv().unwrap())
|
Ok(response_receiver.recv().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&self, ticket_patch: TicketPatch) -> Result<(), OverloadedError> {}
|
pub fn update(&self, ticket_patch: TicketPatch) -> Result<(), OverloadedError> {
|
||||||
|
let (sender, receiver) = sync_channel(1);
|
||||||
|
self.sender
|
||||||
|
.try_send(Command::Update {
|
||||||
|
patch: ticket_patch,
|
||||||
|
response_channel: sender,
|
||||||
|
})
|
||||||
|
.map_err(|_| OverloadedError)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
@@ -85,7 +93,23 @@ pub fn server(receiver: Receiver<Command>) {
|
|||||||
patch,
|
patch,
|
||||||
response_channel,
|
response_channel,
|
||||||
}) => {
|
}) => {
|
||||||
todo!()
|
let ticket = store.get_mut(patch.id).unwrap();
|
||||||
|
match patch.title {
|
||||||
|
Some(a) => {
|
||||||
|
ticket.title = a;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match patch.status {
|
||||||
|
Some(a) => ticket.status = a,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
match patch.description {
|
||||||
|
Some(a) => ticket.description = a,
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// There are no more senders, so we can safely break
|
// There are no more senders, so we can safely break
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ impl TicketStore {
|
|||||||
description: ticket.description,
|
description: ticket.description,
|
||||||
status: Status::ToDo,
|
status: Status::ToDo,
|
||||||
};
|
};
|
||||||
todo!();
|
self.tickets.insert(id, Arc::new(Mutex::new(ticket)));
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
// The `get` method should return a handle to the ticket
|
// The `get` method should return a handle to the ticket
|
||||||
// which allows the caller to either read or modify the ticket.
|
// which allows the caller to either read or modify the ticket.
|
||||||
pub fn get(&self, id: TicketId) -> Option<todo!()> {
|
pub fn get(&self, id: TicketId) -> Option<Arc<Mutex<Ticket>>> {
|
||||||
todo!()
|
self.tickets.get(&id).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// TODO: Replace `Mutex` with `RwLock` in the `TicketStore` struct and
|
// TODO: Replace `Mutex` with `RwLock` in the `TicketStore` struct and
|
||||||
// all other relevant places to allow multiple readers to access the ticket store concurrently.
|
// all other relevant places to allow multiple readers to access the ticket store concurrently.
|
||||||
use std::sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError};
|
use std::sync::mpsc::{sync_channel, Receiver, SyncSender, TrySendError};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
use crate::data::{Ticket, TicketDraft};
|
use crate::data::{Ticket, TicketDraft};
|
||||||
use crate::store::{TicketId, TicketStore};
|
use crate::store::{TicketId, TicketStore};
|
||||||
@@ -26,7 +26,7 @@ impl TicketStoreClient {
|
|||||||
Ok(response_receiver.recv().unwrap())
|
Ok(response_receiver.recv().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, id: TicketId) -> Result<Option<Arc<Mutex<Ticket>>>, OverloadedError> {
|
pub fn get(&self, id: TicketId) -> Result<Option<Arc<RwLock<Ticket>>>, OverloadedError> {
|
||||||
let (response_sender, response_receiver) = sync_channel(1);
|
let (response_sender, response_receiver) = sync_channel(1);
|
||||||
self.sender
|
self.sender
|
||||||
.try_send(Command::Get {
|
.try_send(Command::Get {
|
||||||
@@ -55,7 +55,7 @@ enum Command {
|
|||||||
},
|
},
|
||||||
Get {
|
Get {
|
||||||
id: TicketId,
|
id: TicketId,
|
||||||
response_channel: SyncSender<Option<Arc<Mutex<Ticket>>>>,
|
response_channel: SyncSender<Option<Arc<RwLock<Ticket>>>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use crate::data::{Status, Ticket, TicketDraft};
|
use crate::data::{Status, Ticket, TicketDraft};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct TicketId(u64);
|
pub struct TicketId(u64);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TicketStore {
|
pub struct TicketStore {
|
||||||
tickets: BTreeMap<TicketId, Arc<Mutex<Ticket>>>,
|
tickets: BTreeMap<TicketId, Arc<RwLock<Ticket>>>,
|
||||||
counter: u64,
|
counter: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,14 +28,14 @@ impl TicketStore {
|
|||||||
description: ticket.description,
|
description: ticket.description,
|
||||||
status: Status::ToDo,
|
status: Status::ToDo,
|
||||||
};
|
};
|
||||||
let ticket = Arc::new(Mutex::new(ticket));
|
let ticket = Arc::new(RwLock::new(ticket));
|
||||||
self.tickets.insert(id, ticket);
|
self.tickets.insert(id, ticket);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
// The `get` method should return a handle to the ticket
|
// The `get` method should return a handle to the ticket
|
||||||
// which allows the caller to either read or modify the ticket.
|
// which allows the caller to either read or modify the ticket.
|
||||||
pub fn get(&self, id: TicketId) -> Option<Arc<Mutex<Ticket>>> {
|
pub fn get(&self, id: TicketId) -> Option<Arc<RwLock<Ticket>>> {
|
||||||
self.tickets.get(&id).cloned()
|
self.tickets.get(&id).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use without_channels::store::TicketStore;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn works() {
|
fn works() {
|
||||||
let store = todo!();
|
let store = Arc::new(RwLock::new(TicketStore::new()));
|
||||||
|
|
||||||
let store1 = store.clone();
|
let store1 = store.clone();
|
||||||
let client1 = spawn(move || {
|
let client1 = spawn(move || {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Not much to be exercised on `Sync`, just a thing to remember.
|
// Not much to be exercised on `Sync`, just a thing to remember.
|
||||||
fn outro() -> &'static str {
|
fn outro() -> &'static str {
|
||||||
"I have a good understanding of __!"
|
"I have a good understanding of Send and Sync!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn intro() -> &'static str {
|
fn intro() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to _!"
|
"I'm ready to learn about futures!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user