我想打电话给一个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的适用性错误?
无法从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)