为什么在调用函数中看不到 putTMVar 的函数中填充了 TMVar?

Why is a TMVar populated in a function with putTMVar not visible from the calling function?

在下面的代码中,我发送了一个 IO (TMVar o) 关闭的记录以填充到一个函数中,然后读取 我认为当函数returns时应该是相同的TMVar。问题是当我读回它时它是空的并且应用程序只是阻塞。

为什么会这样?

Hook初始化如下:

hook = Hook { 
  -- other props
  hookResult = newEmptyTMVarIO,
 }

稍后在 ap:

executeHook :: (Text -> IO ()) -> Node i o -> IO ()
executeHook db =
  \case
    Fixture {} -> pure ()
    Hook
      { hookParent,
        hookStatus,
        hook,
        hookResult, -- IO (TMVar o)
        hookChildren
      } -> do
        input <- db "CALL PARENT LOCK EXECUTE HOOK" >> lockExecuteHook db hookParent
        result <- hook input
        hr <- hookResult
        mtb <- atomically $ isEmptyTMVar hr
        db $ "HOOK RESULT PUT EMPTY BEFORE: " <> txt mtb 
        atomically $ putTMVar hr result -- writes hook result to the TMVar
        mt <- atomically $ isEmptyTMVar hr
        db $ "HOOK RESULT PUT EMPTY AFTER: " <> txt mt 

lockExecuteHook :: (Text -> IO ()) -> Either o (Node i o) -> IO o
lockExecuteHook db parent =
  eitherf
    parent
    (\o -> db "NO PARENT HOOK RETURNING VALUE" >> pure o)
    ( \case
        Fixture {} -> pure ()
        hk@Hook
          { hookParent,
            hookStatus,
            hookResult, -- IO (TMVar o)
            hook,
            hookChildren,
            hookRelease
          } -> do
            bs <- hookStatus
            wantLaunch <- atomically $ tryLock db bs
            db $ "HOOK LOCK >>> " <> txt wantLaunch
            when
              wantLaunch
              $ executeHook db hk --  this writes hook result to the TMVar
            hr <- hookResult
            mt <- atomically $ isEmptyTMVar hr
            db $ "READING HOOK !!!!!!!!!!!!!!!!!!!!!!!!!! EMPTY: " <> txt mt
            r <- atomically $ readTMVar hr
            db "RETURNING FROM LOCK EXECUTE HOOK " >> pure r
    )

调试 (db) 输出

CALL PARENT LOCK EXECUTE HOOK
HOOK LOCK >>> True
HOOK RESULT PUT EMPTY BEFORE: True
HOOK RESULT PUT EMPTY AFTER: False
READING HOOK !!!!!!!!!!!!!!!!!!!!!!!!!! EMPTY: True

正如@FyodorSoikin、@DanielWagner 和@chi 在上述评论中指出的那样,它没有按预期工作的原因是 hookResult 没有正确初始化。

将记录字段设置为 IO (TMVar a) 将导致每次读取 hookResult 时都会产生一个新的 TMVar a,如果将字段设置为 [=15] 也会出现类似的问题=] 使用 newTMVar。要使这项工作正常,需要在 IO 或 STM 上下文中将 hookResult 设置为 TMVar a

eg :: IO (Hook a)
eg = do
       v <- newEmptyTMVarIO
       pure $ Hook { 
         -- other props
         hookResult = v,
       }