「a」を正常に返すか、タイムアウト「b」が原因で、同時実行 haskell で関数を実装するにはどうすればよいですか?
timed :: Int → IO a → b → IO (Either a b)
timed max act def = do
宜しくお願いします、
Cetin Sert
注: timed の署名は、完全にまたはわずかに異なる場合があります。
「a」を正常に返すか、タイムアウト「b」が原因で、同時実行 haskell で関数を実装するにはどうすればよいですか?
timed :: Int → IO a → b → IO (Either a b)
timed max act def = do
宜しくお願いします、
Cetin Sert
注: timed の署名は、完全にまたはわずかに異なる場合があります。
timed
上にあなたの希望を実装するのSystem.Timeout.timeout
は簡単です:
import System.Timeout (timeout)
timed :: Int -> IO a -> b -> IO (Either b a)
timed us act def = liftM (maybe (Left def) Right) (timeout us act)
ちなみに、 の一般的な実装は次のようtimeout
になります: ( $!
=seq
サンクを返すだけでなく、スレッドで返された値の評価を強制しようとする):
import Control.Concurrent (forkIO, threadDelay, killThread)
import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
import System.IO (hPrint, stderr)
timeout :: Int -> IO a -> IO (Maybe a)
timeout us act = do
mvar <- newEmptyMVar
tid1 <- forkIO $ (putMVar mvar . Just $!) =<< act
tid2 <- forkIO $ threadDelay us >> putMVar mvar Nothing
res <- takeMVar mvar
killThread (maybe tid1 (const tid2) res) `catch` hPrint stderr
return res
ライブラリでの の実装はSystem.Timeout.timeout
もう少し複雑で、より例外的なケースを処理します。
import Control.Concurrent (forkIO, threadDelay, myThreadId, killThread)
import Control.Exception (Exception, handleJust, throwTo, bracket)
import Data.Typeable
import Data.Unique (Unique, newUnique)
data Timeout = Timeout Unique deriving Eq
timeoutTc :: TyCon
timeoutTc = mkTyCon "Timeout"
instance Typeable Timeout where { typeOf _ = mkTyConApp timeoutTc [] }
instance Show Timeout where
show _ = "<<timeout>>"
instance Exception Timeout
timeout n f
| n < 0 = fmap Just f
| n == 0 = return Nothing
| otherwise = do
pid <- myThreadId
ex <- fmap Timeout newUnique
handleJust (\e -> if e == ex then Just () else Nothing)
(\_ -> return Nothing)
(bracket (forkIO (threadDelay n >> throwTo pid ex))
(killThread)
(\_ -> fmap Just f))
これが私が思いついた最初の答えです。ポートスキャナーにはこれが必要でした。o_O ルーターの管理者パスワードを忘れてしまったので、再利用して再利用できるようになる前にホームサーバーで開いていたポートを確認したかったのです ^ _ ^" ... この実装は当面の仕事をするはずです.
module Control.Concurrent.Timed (timed) where
import Prelude hiding (take)
import System.IO
import Control.Monad
import System.Process
import System.Timeout
import Control.Concurrent
import System.Environment
timed :: Int → IO a → b → IO (Either b a)
timed max act def = do
w ← new
r ← new
t ← forkIO $ do
a ← act
r ≔ Right a
e ← em w
case e of
False → kill =<< take w
True → return ()
s ← forkIO $ do
(w ≔) =<< mine
wait max
e ← em r
case e of
True → do
kill t
r ≔ Left def
False → return ()
take r
timed_ :: Int → IO a → a → IO a
timed_ max act def = do
r ← timed max act def
return $ case r of
Right a → a
Left a → a
(≔) = putMVar
new = newEmptyMVar
wait = threadDelay
em = isEmptyMVar
kill = killThread
mine = myThreadId
take = takeMVar
または単にSystem.Timeout.timeoutを使用します-__-"