Shellyライブラリを使用して一連のタスクを並行して実行する簡単なスクリプトを作成していますが、一度に実行するタスクの最大数を制限したいと思います。スクリプトは、各行に入力があるファイルを取得し、その入力に対してタスクを実行します。ファイルには数百の入力があり、一度に約16プロセスに制限したいと思います。
現在のスクリプトは、初期カウントが1のQSemを使用して、実際には1に制限されています(うまく試行されます)。ただし、4つの入力を持つテストファイルで実行すると、次のように表示されます。
起動 起動 起動 起動 終わり 終わり 終わり 終わり
したがって、スレッドはQSemでブロックされていません。予想どおり、すべて同時に実行されています。私は自分のセマフォを実装するところまで行ってMVarおりTVar、どちらも期待どおりに機能しませんでした。私は明らかに基本的な何かが欠けていますが、何ですか?また、コードをコンパイルしてバイナリとして実行してみました。
#!/ usr / bin / env runhaskell
{-#言語TemplateHaskell、QuasiQuotes、DeriveDataTypeable、OverloadedStrings#-}
Shellyをインポートする
プレリュード非表示のインポート(FilePath)
Text.Shakespeare.Text(lt)をインポートします
修飾されたData.Text.LazyをLTとしてインポートします
Control.Monad(forM)をインポートします
System.Environment(getArgs)をインポートします
修飾されたControl.Concurrent.QSemをQSemとしてインポートします
Control.Concurrentをインポートします(forkIO、MVar、putMVar、newEmptyMVar、takeMVar)
-同時プロセスの最大数を定義します
maxProcesses :: IO QSem.QSem
maxProcesses = QSem.newQSem 1
bkGrnd :: ShIO a-> ShIO(MVar a)
bkGrnd proc = do
mvar <-liftIO newEmptyMVar
_ <-liftIO $ forkIO $ do
-空きプロセスができるまでブロックします
sem <-maxProcesses
QSem.waitQSem sem
putStrLn「開始中」
-シェルコマンドを実行します
結果<-shelly$サイレントproc
liftIO $putMVarmvar結果
putStrLn「完了」
-このプロセスが完了し、別のプロセスを実行できることを通知します。
QSem.signalQSem sem
mvarを返す
メイン::IO()
main =shelly$サイレント$do
[img、ファイル] <-liftIO $ getArgs
内容<-readfile$fromText$LT.packファイル
-入力の各行に対してバックグラウンドプロセスを実行します。
結果<-forM(LT.linesコンテンツ)$ \ line-> bkGrnd $ do
runStdin<コマンド><引数>
liftIO $mapM_takeMVarの結果