LINUX.ORG.RU

Signal Handler — как сделать лучше?

 ,


0

3

Есть код, который должен возвращать промежуточный результат при keyboard interruption. Пока я реализовал топорное решение: signal handler что-то пишет в некий MVar, а код вычисления этот MVar периодически проверяет. Всё работает, но это убого.

А как бы эту задачу решил %username%? Поделитесь best practices.


Ответ на: комментарий от fmdw

можешь объяснить каким чудом unsafeInterleaveIO делает тут это все работать? И чего у всей этой радости будет со сложностью по памяти.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

а то моё дурацкое решение, что выше у меня отрабатывает слегка побыстрее (без оптимизаций правда). или я не правильно использую твой fix'?

{-# LANGUAGE LambdaCase #-}
import Control.Concurrent
import System.IO.Unsafe

calc _ 0 = 0
calc f n = f $ n-1

fix' s f = readMVar s >>= \case 
   False -> do
        a <- unsafeInterleaveIO (fix' s f)
	return $ f a
   True -> return $ f id

test = do
  fin <- newEmptyMVar
  x <- newMVar False
  t <- forkIO $ fix' x calc >>= print . ($150000) >> putMVar fin ()
  -- yield
  -- _ <- swapMVar x True
  takeMVar fin

data CFix a b = CFix a (a -> CFix a b)
              | Result a

calcc 0 = Result 0
calcc n = CFix (n-1) calcc

run _ (Result v) = return v
run s (CFix v f) = readMVar s >>= \case
  False -> run s (f v)
  True  -> return v

testc = do
  fin <- newEmptyMVar
  x <- newMVar False
  t <- forkIO $ run x (calcc 150000) >>= print >> putMVar fin ()
  -- yield
  -- _ <- swapMVar x True
  takeMVar fin

ghci:

*Main> testc
0
(0.27 secs, 71795496 bytes)
*Main> test
0
(0.40 secs, 143504040 bytes)
qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Это вариант unsafePerformIO, который откладывает IO действие до востребования в чистом коде. Его используют для lazy IO, например.

По поводу сложности по памяти — тут вроде не tail call, так что этот код годится только поржать.

fmdw
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.