В следующей программе число Фибоначчи генерируется из заданного целого (генерируется случайным образом), и это значение сохраняется в TVar. Поскольку время выполнения для создания Фибоначчи различно для разных чисел, таким образом, потоки не будут выполняться последовательно. Я хочу сохранить theadID, может быть в списке, чтобы проверить их шаблон выполнения. Пожалуйста, помогите мне. Заранее спасибо.Haskell STM: как хранить ThreadID согласно их последовательности выполнения
module Main
where
import Control.Parallel
import Control.Concurrent.STM
import Control.Concurrent
import System.Random
import Control.Monad
import Data.IORef
import System.IO
nfib :: Int -> Int
nfib n | n <= 2 = 1
| otherwise = par n1 (pseq n2 (n1 + n2))
where n1 = nfib (n-1)
n2 = nfib (n-2)
type TInt = TVar Int
updateNum :: TInt -> Int -> STM()
updateNum n v = do x1 <- readTVar n
let y = nfib v
x2 <- readTVar n
if x1 == x2
then writeTVar n y
else retry
updateTransaction :: TInt -> Int -> IO()
updateTransaction n v = do atomically $ updateNum n v
incR :: IORef Int -> Int -> IO()
incR r x = do { v <- readIORef r;
writeIORef r (v - x) }
main :: IO()
main = do
n <- newTVarIO 10
r <- newIORef 40;
forM_ [1..10] (\i -> do
incR r i
;v <- readIORef r
;forkIO (updateTransaction n v)
)
Я хочу сохранить [TreadID, FibNo] в список для всех потоков в соответствии с их исполнением. Предположим, что T1 выполнил Fib30, T2 Fib35, T3-> 32 и T4-> 40. И если последовательность фиксации потоков, таких как T1, T3, T2 и T4, тогда я хочу сохранить T1-35, T3-32, t2-35, t4-40 в списке.
Edit: Как было предложено @MathematicalOrchid, я изменил updateTrasaction следующим образом: -
updateTransaction :: MVar [(ThreadId, Int)] -> TInt -> Int -> IO()
updateTransaction mvar n v = do
tid <- myThreadId
atomically $ updateNum n v
list <- takeMVar mvar
putMVar mvar $ list ++ [(tid, v)]
Теперь я пытаюсь вывести значения из этого списка в главном
main :: IO()
main = do
...
...
m <- newEmptyMVar
...
...
mv <- readMVar m
putStrLn ("ThreadId, FibVal : " ++ " = " ++ (show mv))
Во время исполнения. Значения MVar не могут быть считаны и генерируют ошибку
Exception: thread blocked indefinitely in an MVar operation
Что делать? Заранее спасибо.
Вы знаете, что ваша реализация Фибоначчи _really_ медленно? Или вы хотите использовать эту функцию в качестве теста? – Zeta
Функция Фибоначчи как тест. Напр.поскольку Fibonacci 35 займет больше времени, чем Fibonacci 25, и, таким образом, время выполнения для потока 1 (Fib 35) займет больше времени, чем поток 2 (Fib 25). Таким образом, tread2 будет выполняться первым, а затем thead1 (из-за «повтора»). –
'x1 <- readTVar n; ...; x2 <- readTVar n'? Вы знаете, что это совершенно необязательно? – Zeta