AS
Size: a a a
AS
[
[
-fno-omit-yields какие подводные камни?AS
[
IO
Broadcast из пакета concurrent-extra и сделать как-то так (если я правильно запомнил Ваш полный код)main :: IO ()Поллить мвар даже с
main = do
bell <- Broadcast.new
let
thread1 maybeold = do
b <- listen bell
maybe mempty cancel maybeold
if b
then thread1 . Just =<< async do forever $ putStrLn "foo" >> threadDelay 1e6
else thread1 Nothing
thread2 maybeold = do
b <- listen bell
maybe mempty cancel maybeold
if b
then thread2 . Just =<< async do forever $ putStrLn "bar" >> threadDelay 1e6
else thread2 Nothing
void $ forkIO $ thread1 Nothing
void $ forkIO $ thread2 Nothing
void $ forever $ do
flag <- readLn @Int
signal bell $ flag == 1
yieldом идея по мне так себе, просто так проц нагружаем, эффективнее в цикле брать значение из мвара, убивать старый тред с форевером (если был), запускать новый и опять ждать следующего значения из мвара. Тогда если читающий консоль тред записал фолс остальные не крутятся в цикле, а просто спят пока новый сигнал не придет и не мешают другим работать. Читающий тред соответственно должен делать putMVar вместо костыльного modifyMVar . const.Broadcast, который как раз позволяет многим потокам увидеть одну запись (ну или можно использовать стандартный Chan и делать на нем dupChan) (Но теперь надо об исключениях думать, если в listen прилетит то форевер-тред утечет)IO
subscribe :: Broadcast a -> (a -> IO ()) -> IO ()и юзать как
subscribe broad fn = go =<< async mempty
where
go old = do
v <- listen broad `finally` uninterruptibleCancel old
go =<< async do fn v
main :: IO ()
main = do
bell <- Broadcast.new
void $ forkIO $ subscribe bell \b -> when b $ forever $ putStrLn "foo" >> threadDelay 1e6
void $ forkIO $ subscribe bell \b -> when b $ forever $ putStrLn "bar" >> threadDelay 1e6
void $ forever $ do
flag <- readLn @Int
signal bell $ flag == 1
DB
DB
IO
-fno-omit-yields или вставить явный yield руками)DB
DB
YS
YS