如何根据MVar中存储的某些可变状态有条件地将IO操作包装到给定线程中?
我的总体目标是启用超时功能,以便在给定游戏中,如果玩家未在30秒内向服务器发送动作,则套接字msg回调将被调用,并带有特殊的Timeout动作来表示玩家失败。行动。
我正在寻找一种方法,使每个套接字线程能够订阅MVar中包含的游戏状态的更改。
我当前用于创建超时动作的实施草案如下:
-- 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)
总结一下,所有有效的msg都传递给msgCallback函数。然后,该回调将使用新的玩家操作更新纸牌游戏,然后将新的游戏状态广播给所有订阅该游戏的客户端。
与此有关的一个问题是,一旦发生超时,就会在线程内引发异常,从而使正在运行的套接字断开连接。当然,这是不受欢迎的行为。
另一个问题是,此超时是在客户端收到新的消息后实现的。相反,我希望仅在游戏处于特定状态时才执行超时,在该状态下,该特定线程代表的玩家是下一个要行动的玩家。
因此,特定游戏中玩家行为的超时只能同时在最多一个线程中进行。由于纸牌游戏采用回合制动作。
接下来,我需要根据MVar中存储的游戏状态,有条件地包装IO操作以接收带有超时的消息。