如何将System.IO.Unsafe与TVars一起使用?

J F*_*sch 3 haskell

我想打电话给一个UDP的STM事务中发送函数,这样我才能避免类似下面的代码,其中M"被读取(可能是由其他线程更新)之前最终被送到与其中两个连续的where子句让我的价值观看起来很"无奈".

sendRecv s newmsgs q m = do
     m' <- atomically $ readTVar m
     time <- getPOSIXTime
     result <- appendMsg newmsgs key m
     when (result > 0) (atomically $ do 
                           mT <- readTVar m
                           qT <- readTVar q
                           --let Just messages = Map.lookup key mT in sendq s (B.pack $ unwords messages) "192.168.1.1" 4711 
                           let mT' = Map.delete key mT
                               qT' = PSQ.delete key qT
                           writeTVar q (PSQ.insert key time qT')
                           writeTVar m (Map.insert key [newmsgs] mT'))
     when (result > 0) (let Just messages = Map.lookup key m' in sendq s (B.pack $ unwords messages) "192.168.1.1" 4711) 

sendq :: Socket -> B.ByteString -> String -> PortNumber -> IO ()
sendq s datastring host port = do
      hostAddr <- inet_addr host
      sendAllTo s datastring (SockAddrInet port hostAddr)
      return ()
Run Code Online (Sandbox Code Playgroud)

我认为通过调用TVars newTVarIO并使用import System.IO.Unsafe我最终可以使用unsafePerformIO某个地方并IO()从事务中调用我的sendq函数(返回).

但是,我找不到这个"某个地方"的位置?是在TVar的创作?是代替atomically $ do吗?我是否理解unsafePerformIO的适用性错误?

Dan*_*ner 8

无法从STM块内部执行IO,因为无法撤消常规IO.如果要执行某些IO,则必须在STM块中安排它,但在外部执行.例如:

foo tvar = do
    scheduledAction <- atomically $ do
        v <- readTVar tvar
        when v retry
        return (sendSomethingOnASocket "okay, we're done here")
    scheduledAction
Run Code Online (Sandbox Code Playgroud)