Как вы условно переносите действие ввода-вывода в заданном потоке в зависимости от некоторого изменяемого состояния, хранящегося в 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.