package lobby import ( "context" "git.sunturtle.xyz/studio/shotgun/player" "github.com/google/uuid" ) type match struct { dealer player.ID chall chan player.ID match chan GameID } // Queue waits for a match. // This may cause a new match to be created. func (l *Lobby) Queue(ctx context.Context, p player.ID) GameID { select { case <-ctx.Done(): return GameID{} case m := <-l.matches: // We found a dealer waiting for a match. // We don't need to check the context here because the challenger // channel is buffered and we have exclusive send access on it. m.chall <- p // We do need to check the context here in case they disappeared. select { case <-ctx.Done(): return GameID{} case id := <-m.match: return id } default: // do nothing } // We're a new dealer. m := match{ dealer: p, chall: make(chan player.ID, 1), match: make(chan GameID, 1), } select { case <-ctx.Done(): return GameID{} case l.matches <- m: // Our match is submitted. Move on. case m := <-l.matches: // We might have become a dealer at the same time someone else did. // We created our match, but we can try to get theirs as well and // never send ours, since l.matches is unbuffered. m.chall <- p select { case <-ctx.Done(): return GameID{} case id := <-m.match: return id } } select { case <-ctx.Done(): return GameID{} case chall := <-m.chall: // Got our challenger. Create the game and send the ID back. id := uuid.New() l.Start(id, p, chall) // Don't need to check context because the match channel is buffered. m.match <- id return id } }