Browse Source

Fix deadlock when on_click is called

new_protocol
ThePerkinrex 5 years ago
parent
commit
44a1761c05
No known key found for this signature in database GPG Key ID: 1F45A7C4BFB41607
  1. 82
      server/src/server/game.rs
  2. 4
      unity/Assets/Scripts/Client.cs

82
server/src/server/game.rs

@ -49,7 +49,7 @@ impl GameService {
None => return Err(Status::failed_precondition("User isn't in a lobby")), None => return Err(Status::failed_precondition("User isn't in a lobby")),
}; };
let games_lock = self.running_games.read().await; // This encounters a deadlock 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) { let game_lock = match games_lock.get(&lobby) {
Some(x) => x.read().await, Some(x) => x.read().await,
None => { None => {
@ -149,7 +149,6 @@ impl GameService {
} }
async fn get_default_status(&self, uuid: uuid::Uuid) -> Result<Option<MessageStatus>, Status> { async fn get_default_status(&self, uuid: uuid::Uuid) -> Result<Option<MessageStatus>, Status> {
log::info!("Getting the deafult status for {}", uuid); log::info!("Getting the deafult status for {}", uuid);
let lobby = { let lobby = {
let mut conn = self.conn.write().await; let mut conn = self.conn.write().await;
@ -159,8 +158,7 @@ impl GameService {
}; };
lobby lobby
}; };
let r = let r = Ok(self
Ok(self
.running_games .running_games
.read() .read()
.await .await
@ -173,7 +171,7 @@ impl GameService {
.2 .2
.get() .get()
.clone()); .clone());
log::info!("Gotten the deafult status for {}", uuid); log::info!("Gotten the deafult status for {}", uuid);
r r
} }
} }
@ -214,7 +212,6 @@ impl game_server::Game for GameService {
// log::info!("Loading back image [{:?}]", time.elapsed()); // log::info!("Loading back image [{:?}]", time.elapsed());
let back_buf = tokio::fs::read(back).await.unwrap(); let back_buf = tokio::fs::read(back).await.unwrap();
log::info!("Loaded images [{:?}]", time.elapsed()); log::info!("Loaded images [{:?}]", time.elapsed());
Ok(Response::new(Image { Ok(Response::new(Image {
face: face_buf, face: face_buf,
@ -228,39 +225,44 @@ impl game_server::Game for GameService {
) -> Result<tonic::Response<()>, Status> { ) -> Result<tonic::Response<()>, Status> {
let uuid = client_id::get(request.metadata()).map_err(|x| match x { 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::NotSet => Status::failed_precondition("client_id must be set"),
client_id::Error::MalformedUuid => Status::failed_precondition("malformed client_id"), 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",
))
} }
}; })?;
let game = &mut game_lock.1; {
let card = request.into_inner(); let mut conn = self.conn.write().await;
let idx = match card.card_index.unwrap().pos.unwrap() { let lobby: u32 = match conn.get_lobby_for_user(uuid).await {
super::grpc::game::card_index::Pos::Bottom(()) => CardIdx::Bottom, Some(l) => l,
super::grpc::game::card_index::Pos::Top(()) => CardIdx::Top, None => return Err(Status::failed_precondition("User isn't in a lobby")),
super::grpc::game::card_index::Pos::Index(x) => CardIdx::Indexed(x as usize), };
}; log::debug!("{} clicked a card in the lobby {}", uuid, lobby);
let pile_kind = match card.pile_kind.unwrap().kind.unwrap() { let games_lock = self.running_games.read().await;
super::grpc::game::pile_kind::Kind::Common(()) => PileKind::Common, let mut game_lock = match games_lock.get(&lobby) {
super::grpc::game::pile_kind::Kind::Owned(p) => PileKind::Owned(p), Some(x) => x.write().await,
}; None => {
let card: CardId = CardId { return Err(Status::failed_precondition(
idx, "User isn't in a lobby with a running game",
pile_kind, ))
pile_name: card.pile_name, }
}; };
game.on_click(card, game.get_player_for_uuid(&uuid).unwrap()); 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?; self.update_status(uuid).await?;
Ok(Response::new(())) Ok(Response::new(()))
} }
@ -282,9 +284,7 @@ impl game_server::Game for GameService {
r r
}); });
log::info!("Status is acquired"); log::info!("Status is acquired");
let r= Ok(Response::new( let r = Ok(Response::new(status));
status,
));
log::info!("Given game status to {}", uuid); log::info!("Given game status to {}", uuid);
r r
} }

4
unity/Assets/Scripts/Client.cs

@ -210,12 +210,12 @@ public static class Client
public int GetUserIndex(string user) { public int GetUserIndex(string user) {
var status = game_client.status(new Google.Protobuf.WellKnownTypes.Empty(), new Metadata { new Metadata.Entry("client_id", connId) }); 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<string, Dictionary<string, Game.MessageStatus.Types.Pile>> OnClickCard(string pileName, bool isCommonPile, int cardIdx, string user) { public Dictionary<string, Dictionary<string, Game.MessageStatus.Types.Pile>> OnClickCard(string pileName, bool isCommonPile, int cardIdx, string user) {
Game.PileKind pileKind = new Game.PileKind() { Owned = (uint)GetUserIndex(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); return GetPiles(user);
} }

Loading…
Cancel
Save