前回のデバッグ実行するプログラムを改良してみた。
キー入力と実行関数の再帰部分をモジュール化した。
これでメインルーチンはすっきりした。
module DebugRun where import Control.Concurrent import System.IO.Unsafe data St = Run | Debug | Wait deriving (Eq) -- like global value st = unsafePerformIO $ newMVar Run putMVarForce :: MVar a -> a -> IO () putMVarForce mv d = do emp <- isEmptyMVar mv if emp == True then putMVar mv d else takeMVar mv >>= \_ -> putMVar mv d waitloop :: IO () -> IO () waitloop iofunc = do st2 <- readMVar st if st2 == Run then iofunc else do putMVarForce st Wait waitloop' iofunc where waitloop' :: IO () -> IO () waitloop' iofunc = do st2 <- readMVar st if st2 == Wait then waitloop' iofunc else iofunc keyloop :: ThreadId -> IO () keyloop ou = do k <- getChar case k of 'r' -> putMVarForce st Run 'd' -> putMVarForce st Debug _ -> return () if k == 'q' then killThread ou else keyloop ou
module Keyin2 where import Control.Concurrent import DebugRun outgo :: String -> IO () outgo [] = do { print ""; putStrLn "thread end."; } outgo (x:xs) = do print (x:xs) threadDelay (1*1000*1000) waitloop $ outgo xs main = do ou <- forkIO $ outgo "asdfghjklqwerty" keyloop ou putStrLn "main end."
・実行関数が終わったときに、外からgetCharを止める方法がどうしても思いつかなかった。
・禁断のunsafePerformIOに手を染めてしまった。