【问题标题】:Understanding Logging Example in Parallel and Concurrent Haskell了解并行和并发 Haskell 中的日志记录示例
【发布时间】:2017-10-22 20:44:58
【问题描述】:

在来自Parallel and Concurrent Haskell 的 MVar 日志记录示例中,它显示以下内容:

import Control.Concurrent
import Control.Concurrent.MVar

data Logger = Logger (MVar LogCommand)

data LogCommand = Message String | Stop (MVar ())

initLogger :: IO Logger
initLogger = do
  m <- newEmptyMVar
  let l = Logger m
  forkIO (logger l)
  return l

logger :: Logger -> IO ()
logger (Logger m) = loop
  where 
   loop = do
    cmd <- takeMVar m
    case cmd of 
      Message msg -> putStrLn msg >> loop
      Stop s -> do
        putStrLn "logger: stop"
        putMVar s ()

logMessage :: Logger -> String -> IO ()
logMessage (Logger m) s = putMVar m (Message s)

logStop :: Logger -> IO ()
logStop (Logger m) = do
  s <- newEmptyMVar
  putMVar m (Stop s)
  takeMVar s

如果删除logger 的最后一行,即putMVar s (),会丢失什么?

【问题讨论】:

  • 你试过了吗?
  • 没有。谢谢你打电话给我。我应该问一个问题。

标签: haskell


【解决方案1】:

没有putMVar s (),调用logStop 将挂起takeMVar s,因为没有其他东西可以填充s。最终会抛出BlockedIndefinitelyOnMVar 异常,杀死挂起的线程。

s 用于有序关机。它保证在logStop返回时,日志处理线程实际上已经停止。

另请参阅您链接的页面中的此文本:

[...] logStop 导致日志服务终止。后面的操作很重要,因为如果我们想关闭程序,我们需要确保日志服务已经完成了所有未完成的请求的处理。回想一下“A Simple Example: Reminders”,当主线程退出时,程序会立即终止,而不是等待其他线程先终止。因此logStop 有一个额外的要求:在日志服务处理完所有未完成的请求并停止之前,它不能返回。

[...]

发送命令后,我们在新的MVar 上调用takeMVar 等待响应。日志记录线程处理完Stop 命令后,会将() 放入此MVar,这允许takeMVar 继续,logStop 返回。

【讨论】:

  • 谢谢!那么,去掉logStop中的takeMVar s合理吗?
  • @KevinMeredith ...你读过我引用的第一段吗?
猜你喜欢
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2017-09-23
  • 1970-01-01
  • 1970-01-01
  • 2014-01-22
相关资源
最近更新 更多