Как подписаться на изменения состояния в потоках? - PullRequest
0 голосов
/ 30 июня 2018

Как вы условно переносите действие ввода-вывода в заданном потоке в зависимости от некоторого изменяемого состояния, хранящегося в MVar?

Моя общая цель состоит в том, чтобы включить тайм-ауты, чтобы в данной игре, если игрок не отправил действие на сервер в течение 30 секунд, был вызван обратный вызов сокета msg со специальным действием тайм-аута для обозначения отказа игрока акт.

Я ищу способ, позволяющий каждому потоку сокета подписаться на изменение состояния игры, содержащееся в MVar.

Моя текущая черновая реализация для создания действия Timeout выглядит следующим образом:

-- This function processes msgs from authenticated clients
authenticatedMsgLoop ::
     (MsgIn -> ReaderT MsgHandlerConfig (ExceptT Err IO) ())
  -> MsgHandlerConfig
  -> IO ()
authenticatedMsgLoop msgCallback msgHandlerConfig@MsgHandlerConfig {..}
 = do
  finally
       (forever $ do
          maybeMsg <- timeout 1000000 (WS.receiveData clientConn)
          let parsedMsg = maybe (Just Timeout) parseMsgFromJSON maybeMsg
          for_ parsedMsg $ \parsedMsg -> do
            result <-
              runExceptT $ runReaderT (msgCallback parsedMsg) msgHandlerConfig
            either (\err -> sendMsg clientConn $ ErrMsg err) return result)
          return ())
    (removeClient username serverState)

Для суммирования все действительные сообщения передаются в функцию msgCallback. Этот обратный вызов затем обновит карточную игру новым действием игрока, а затем передаст новое игровое состояние всем клиентам, которые подписаны на игру.

Одна из проблем заключается в том, что, как только происходит тайм-аут, в потоке создается исключение, которое отключает работающий сокет. Это, конечно, нежелательное поведение.

Другая проблема заключается в том, что этот тайм-аут реализован после получения клиентом нового сообщения. Вместо этого я хотел бы, чтобы тайм-аут был реализован только тогда, когда игра находится в определенном состоянии - это состояние, в котором игрок, представленный этим конкретным потоком, является следующим игроком, который будет действовать.

Следовательно, тайм-аут для действия игрока в конкретной игре может быть введен не более чем в один поток одновременно. Поскольку в карточной игре используются пошаговые действия.

Отсюда следует, что мне нужно условно обернуть действие ввода-вывода для получения сообщений с таймаутом в зависимости от состояния игры, которое хранится в MVar.

1 Ответ

0 голосов
/ 30 июня 2018

Я бы использовал Chan или TChan , чтобы подписать каждый поток на состояние игры. Когда состояние изменяется, я проверю, является ли текущий игрок тем же игроком потока. Затем либо вернитесь к ожиданию следующего сообщения на TChan, либо запустите таймер для пользовательского ввода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...