diff --git a/server/src/api.rs b/server/src/api.rs index 102ed8f..b994ced 100644 --- a/server/src/api.rs +++ b/server/src/api.rs @@ -83,7 +83,7 @@ async fn handle_new_user( .await?; // Register using `addr` as key until something longer lived exists - state.online_users.lock().unwrap().insert(*addr, new_user); + state.online_users.write().unwrap().insert(*addr, new_user); // Hydrate client // this should probably be combined and sent as one @@ -127,7 +127,7 @@ fn chat_meta_update(state: &Arc) -> String { // this may get expensive if there are many users let mut names = vec![]; - for user in state.online_users.lock().unwrap().iter() { + for user in state.online_users.read().unwrap().iter() { names.push(user.1.read().unwrap().name.clone()); } @@ -148,8 +148,8 @@ fn motd() -> String { /// Generate server summary update - mostly debug stuff fn server_summary_update(state: &Arc) -> String { - let online_users = state.online_users.lock().unwrap().len(); - let active_games = state.games.lock().unwrap().len(); + let online_users = state.online_users.read().unwrap().len(); + let active_games = state.games.read().unwrap().len(); to_string::(&ServerStateSummary { online_users, active_games, @@ -162,7 +162,7 @@ fn games_update(state: &Arc) -> String { // this may get expensive if there are many games let mut names = vec![]; - for game in state.games.lock().unwrap().iter() { + for game in state.games.read().unwrap().iter() { names.push(format!( "Name: {} Host: {}", game.name, @@ -179,7 +179,7 @@ fn announce_join(state: &Arc, addr: &SocketAddr) -> String { "{} joined.", state .online_users - .lock() + .read() .unwrap() .get(addr) .unwrap() diff --git a/server/src/api/message_handler.rs b/server/src/api/message_handler.rs index b7566f0..c05aa2d 100644 --- a/server/src/api/message_handler.rs +++ b/server/src/api/message_handler.rs @@ -58,7 +58,7 @@ fn handle_new_game( name: new_game.name, host: state .online_users - .lock() + .read() .unwrap() .get(&addr) .unwrap() @@ -67,7 +67,7 @@ fn handle_new_game( // create game if let Ok(new_game_object) = Game::new(manifest) { - state.games.lock().unwrap().push(new_game_object); + state.games.write().unwrap().push(new_game_object); tx.send(games_update(state))?; tx.send(server_summary_update(state))?; } @@ -82,7 +82,7 @@ fn handle_chat_message( tx: &Sender, addr: SocketAddr, ) -> Result<()> { - let msg = format! {"{0}: {1}", state.online_users.lock().unwrap().get(&addr).unwrap().read().unwrap().name, chat_message.text}; + let msg = format! {"{0}: {1}", state.online_users.read().unwrap().get(&addr).unwrap().read().unwrap().name, chat_message.text}; tracing::debug!("{msg}"); tx.send(to_string::(&ChatMessage { text: msg })?)?; @@ -98,7 +98,7 @@ fn handle_user_log_in( ) -> Result<()> { let old_name = state .online_users - .lock() + .read() .unwrap() .get(&addr) .unwrap() @@ -108,16 +108,16 @@ fn handle_user_log_in( .clone(); let new_name = user_log_in.username.clone(); - if state.offline_users.lock().unwrap().contains_key(&new_name) { + if state.offline_users.read().unwrap().contains_key(&new_name) { state .online_users - .lock() + .write() .unwrap() .insert( addr, state .offline_users - .lock() + .write() .unwrap() .remove(&new_name) .unwrap(), @@ -134,7 +134,7 @@ fn handle_user_log_in( } else { state .online_users - .lock() + .write() .unwrap() .get_mut(&addr) .unwrap() @@ -154,8 +154,8 @@ fn handle_user_log_in( tracing::debug!( "Online Users: {} Offline Users: {}", - state.online_users.lock().unwrap().len(), - state.offline_users.lock().unwrap().len() + state.online_users.read().unwrap().len(), + state.offline_users.read().unwrap().len() ); tx.send(games_update(state))?; @@ -174,7 +174,7 @@ fn handle_close( "Close received from {0} with code: {1} and reason: {2}", state .online_users - .lock() + .read() .unwrap() .get(&addr) .unwrap() @@ -193,7 +193,7 @@ fn handle_close( "{0} left.", state .online_users - .lock() + .read() .unwrap() .get(&addr) .unwrap() @@ -207,7 +207,7 @@ fn handle_close( tx.send(to_string::(&msg)?)?; let name = state .online_users - .lock() + .read() .unwrap() .get(&addr) .unwrap() @@ -216,9 +216,9 @@ fn handle_close( .name .clone(); - state.offline_users.lock().unwrap().insert( + state.offline_users.write().unwrap().insert( name.clone(), - state.online_users.lock().unwrap().remove(&addr).unwrap(), + state.online_users.write().unwrap().remove(&addr).unwrap(), ); tx.send(server_summary_update(state))?; diff --git a/server/src/main.rs b/server/src/main.rs index 071c838..6fb8b70 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -8,7 +8,7 @@ use std::{ fs::{read_to_string, File}, io::{BufRead, BufReader}, net::SocketAddr, - sync::{Arc, Mutex, RwLock}, + sync::{Arc, RwLock}, }; use tokio::sync::broadcast; use tower_http::services::ServeDir; @@ -104,14 +104,14 @@ fn load_names(path: &str) -> Result> { // Our shared state pub struct AppState { // We require unique usernames. This tracks which usernames have been taken. - online_users: Mutex>>>, - offline_users: Mutex>>>, + online_users: RwLock>>>, + offline_users: RwLock>>>, // Channel used to send messages to all connected clients. tx: broadcast::Sender, // Master card decks all_cards: Vec, // Games list - games: Mutex>, + games: RwLock>, // chatrooms: Mutex>>, first_names: Vec, last_names: Vec, @@ -131,10 +131,10 @@ async fn main() -> Result<()> { // Set up application state for use with with_state(). // Main Broadcast Channel let (tx, _rx) = broadcast::channel(100); - let online_users = Mutex::new(HashMap::>>::new()); - let offline_users = Mutex::new(HashMap::>>::new()); + let online_users = RwLock::new(HashMap::>>::new()); + let offline_users = RwLock::new(HashMap::>>::new()); let all_cards = load_cards_from_json("data/cah-cards-full.json")?; - let games = Mutex::new(vec![]); + let games = RwLock::new(vec![]); let first_names = load_names("data/first.txt")?; let last_names = load_names("data/last.txt")?;