From 44a1761c05921f4d0d69b0837af10ce58fc34fc4 Mon Sep 17 00:00:00 2001 From: ThePerkinrex Date: Fri, 25 Dec 2020 11:59:31 +0100 Subject: [PATCH] Fix deadlock when on_click is called --- server/src/server/game.rs | 84 +++++++++++++++++----------------- unity/Assets/Scripts/Client.cs | 4 +- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/server/src/server/game.rs b/server/src/server/game.rs index 1bf0603..ad7c7e3 100644 --- a/server/src/server/game.rs +++ b/server/src/server/game.rs @@ -49,7 +49,7 @@ impl GameService { None => return Err(Status::failed_precondition("User isn't in a lobby")), }; let games_lock = self.running_games.read().await; // This encounters a deadlock - // log::info!("Locked games"); + // log::info!("Locked games"); let game_lock = match games_lock.get(&lobby) { Some(x) => x.read().await, None => { @@ -149,7 +149,6 @@ impl GameService { } async fn get_default_status(&self, uuid: uuid::Uuid) -> Result, Status> { - log::info!("Getting the deafult status for {}", uuid); let lobby = { let mut conn = self.conn.write().await; @@ -159,8 +158,7 @@ impl GameService { }; lobby }; - let r = - Ok(self + let r = Ok(self .running_games .read() .await @@ -173,7 +171,7 @@ impl GameService { .2 .get() .clone()); - log::info!("Gotten the deafult status for {}", uuid); + log::info!("Gotten the deafult status for {}", uuid); r } } @@ -210,10 +208,9 @@ impl game_server::Game for GameService { tokio::task::yield_now().await; } let face_buf = tokio::fs::read(face).await.unwrap(); - + // log::info!("Loading back image [{:?}]", time.elapsed()); let back_buf = tokio::fs::read(back).await.unwrap(); - log::info!("Loaded images [{:?}]", time.elapsed()); Ok(Response::new(Image { @@ -228,39 +225,44 @@ impl game_server::Game for GameService { ) -> Result, Status> { let uuid = client_id::get(request.metadata()).map_err(|x| match x { client_id::Error::NotSet => Status::failed_precondition("client_id must be set"), - client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), - })?; - let mut conn = self.conn.write().await; - let lobby: u32 = match conn.get_lobby_for_user(uuid).await { - Some(l) => l, - None => return Err(Status::failed_precondition("User isn't in a lobby")), - }; - let games_lock = self.running_games.read().await; - let mut game_lock = match games_lock.get(&lobby) { - Some(x) => x.write().await, - None => { - return Err(Status::failed_precondition( - "User isn't in a lobby with a running game", - )) + client_id::Error::MalformedUuid => { + Status::failed_precondition("malformed client_id") } - }; - let game = &mut game_lock.1; - let card = request.into_inner(); - let idx = match card.card_index.unwrap().pos.unwrap() { - super::grpc::game::card_index::Pos::Bottom(()) => CardIdx::Bottom, - super::grpc::game::card_index::Pos::Top(()) => CardIdx::Top, - super::grpc::game::card_index::Pos::Index(x) => CardIdx::Indexed(x as usize), - }; - let pile_kind = match card.pile_kind.unwrap().kind.unwrap() { - super::grpc::game::pile_kind::Kind::Common(()) => PileKind::Common, - super::grpc::game::pile_kind::Kind::Owned(p) => PileKind::Owned(p), - }; - let card: CardId = CardId { - idx, - pile_kind, - pile_name: card.pile_name, - }; - game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()); + })?; + { + let mut conn = self.conn.write().await; + let lobby: u32 = match conn.get_lobby_for_user(uuid).await { + Some(l) => l, + None => return Err(Status::failed_precondition("User isn't in a lobby")), + }; + log::debug!("{} clicked a card in the lobby {}", uuid, lobby); + let games_lock = self.running_games.read().await; + let mut game_lock = match games_lock.get(&lobby) { + Some(x) => x.write().await, + None => { + return Err(Status::failed_precondition( + "User isn't in a lobby with a running game", + )) + } + }; + let game = &mut game_lock.1; + let card = request.into_inner(); + let idx = match card.card_index.unwrap().pos.unwrap() { + super::grpc::game::card_index::Pos::Bottom(()) => CardIdx::Bottom, + super::grpc::game::card_index::Pos::Top(()) => CardIdx::Top, + super::grpc::game::card_index::Pos::Index(x) => CardIdx::Indexed(x as usize), + }; + let pile_kind = match card.pile_kind.unwrap().kind.unwrap() { + super::grpc::game::pile_kind::Kind::Common(()) => PileKind::Common, + super::grpc::game::pile_kind::Kind::Owned(p) => PileKind::Owned(p), + }; + let card: CardId = CardId { + idx, + pile_kind, + pile_name: card.pile_name, + }; + game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()); + } // drop the connection so that the lock is released self.update_status(uuid).await?; Ok(Response::new(())) } @@ -282,9 +284,7 @@ impl game_server::Game for GameService { r }); log::info!("Status is acquired"); - let r= Ok(Response::new( - status, - )); + let r = Ok(Response::new(status)); log::info!("Given game status to {}", uuid); r } diff --git a/unity/Assets/Scripts/Client.cs b/unity/Assets/Scripts/Client.cs index f3ac285..b2f7b46 100644 --- a/unity/Assets/Scripts/Client.cs +++ b/unity/Assets/Scripts/Client.cs @@ -210,12 +210,12 @@ public static class Client public int GetUserIndex(string user) { var status = game_client.status(new Google.Protobuf.WellKnownTypes.Empty(), new Metadata { new Metadata.Entry("client_id", connId) }); - return status.Names.IndexOf(new Common.Name() { Name_ = user }); + return status.Names.IndexOf(new Common.Name { Name_ = user }); } public Dictionary> OnClickCard(string pileName, bool isCommonPile, int cardIdx, string user) { Game.PileKind pileKind = new Game.PileKind() { Owned = (uint)GetUserIndex(user) }; - game_client.onClick(new Game.CardId() { PileKind = pileKind, CardIndex = new Game.CardIndex() { Index = (uint)cardIdx }, PileName = pileName }, new Metadata { new Metadata.Entry("client_id", connId) }); + game_client.onClick(new Game.CardId { PileKind = pileKind, CardIndex = new Game.CardIndex { Index = (uint)cardIdx }, PileName = pileName }, new Metadata { new Metadata.Entry("client_id", connId) }); return GetPiles(user); }