如何避免并行构建中的输出同步问题?

How to avoid output synchronization problems in parallel builds?

在 shake 中使用并行构建时,我得到如下格式错误的输出:

[»] Compiling src/Game/Game.cpp
[»] Compiling [»] Compiling [»] Compiling src/Graphics/Image/Png/PngLoader.cpp
src/Main.cpp
src/System/HeartBeat.cpp
[»] Compiling src/Window/Window.cpp
[»] Compiling src/Window/GlfwContext.cpp

我想这是我打印的某种同步问题。 我应该注意,我使用以下作为输出命令:

shakeOutput = const $ BS.putStr . BS.pack

状态消息打印部分我的规则如下所示:

liftIO $ setSGR [SetColor Foreground Vivid Green]
putNormal "[5] Compiling "
liftIO $ setSGR [SetColor Foreground Vivid Yellow]
putNormal $ c ++ "\n"
liftIO $ setSGR [Reset]

有没有办法避免我在 shake 中内置的输出出现这种打印问题?如果不是的话,哪种haskell同步方法适合使用,知道打印代码在抖动规则内?

shakeOutput 默认为 const $ BS.putStr . BS.pack 的原因是因为 BS.putStr 获取了 Haskell 控制台锁,从而确保输出不会交错。我不认为这是 BS.putStr 的合同保证,但如果它不再如此,我将默认在 shakeOutput 周围添加一个锁。有两种方法可以解决此问题:

加一把锁

一种方法是添加一个锁,最好是一个 renterant Mutex(不是我在 Haskell 中看到的东西,但可以相对容易地在 MVar 和 [=17 之上合成=]).然后你让 shakeOutput 获得锁,并且在多次调用 shakeOutput 的代码片段中你也获得了整个块的锁。 Mutex 可能希望存储在顶级 unsafePerformIO CAF 中。

使用单个 shakeOutput 调用

因为 shakeOutput 已经是原子的,你可以通过重写你的代码来重用 属性:

putNormal $
    setSGRCode [SetColor Foreground Vivid Green] ++
    "[5] Compiling " ++
     setSGRCode [SetColor Foreground Vivid Yellow] ++
     c ++ "\n" ++
     setSGRCode [Reset]

我鼓励第二种方法,因为它更简单,并且还确保如果将冗长变成安静,代码仍然不会被打印出来。

我的方法是使用资源:

con <- newResource "Console" 1
let withConsole = withResource con 1 . liftIO