IORef s, MVar s, and TVar can be used to combine a common variable into a parallel context. I studied parallel hackell for some time, and now I am faced with some questions. After searching on stackoverflow and reading some related questions, my questions are not completely resolved.
To give a specific situation, I will show the actual problem. I have common variables that are never empty, and I want them to be mutable states, so some threads can change these variables at the same time.
Well, it seems that everything TVar decides everything clearly. But I am not satisfied with this, and I am very thirsty for an answer to the above questions. Any help is appreciated.
-------------- re: @GabrielGonzalez BFS interface code ------------------
Below is the code for my BFS interface using the state monad.
{-# LANGUAGE TypeFamilies, FlexibleContexts #-} module Data.Graph.Par.Class where import Data.Ix import Data.Monoid import Control.Concurrent import Control.Concurrent.MVar import Control.Monad import Control.Monad.Trans.State class (Ix (Vertex g), Ord (Edge g), Ord (Path g)) => ParGraph g where type Vertex g :: * type Edge g :: * -- type Path g :: * -- useless type VertexProperty g :: * type EdgeProperty g :: * edges :: ga -> IO [Edge g] vertexes :: ga -> IO [Vertex g] adjacencies :: ga -> Vertex g -> IO [Vertex g] vertexProperty :: Vertex g -> ga -> IO (VertexProperty g) edgeProperty :: Edge g -> ga -> IO (EdgeProperty g) atomicModifyVertexProperty :: (VertexProperty g -> IO (VertexProperty g)) -> Vertex g -> ga -> IO (ga) -- fixed spanForest :: ParGraph g => [Vertex g] -> StateT (ga) IO () spanForest roots = parallelise (map spanTree roots) -- parallel version spanForestSeq :: ParGraph g => [Vertex g] -> StateT (ga) IO () spanForestSeq roots = forM_ roots spanTree -- sequencial version spanTree :: ParGraph g => Vertex g -> StateT (ga) IO () spanTree root = spanTreeOneStep root >>= \res -> case res of [] -> return () adjs -> spanForestSeq adjs spanTreeOneStep :: ParGraph g => Vertex g -> StateT (ga) IO [Vertex g] spanTreeOneStep v = StateT $ \g -> adjacencies gv >>= \adjs -> return (adjs, g) parallelise :: (ParGraph g, Monoid b) => [StateT (ga) IO b] -> StateT (ga) IO b parallelise [] = return mempty parallelise ss = syncGraphOp $ map forkGraphOp ss forkGraphOp :: (ParGraph g, Monoid b) => StateT (ga) IO b -> StateT (ga) IO (MVar b) forkGraphOp t = do s <- get mv <- mapStateT (forkHelper s) t return mv where forkHelper sx = do mv <- newEmptyMVar forkIO $ x >>= \(b, s) -> putMVar mv b return (mv, s) syncGraphOp :: (ParGraph g, Monoid b) => [StateT (ga) IO (MVar b)] -> StateT (ga) IO b syncGraphOp [] = return mempty syncGraphOp ss = collectMVars ss >>= waitResults where collectMVars [] = return [] collectMVars (x:xs) = do mvx <- x mvxs <- collectMVars xs return (mvx:mvxs) waitResults mvs = StateT $ \g -> forM mvs takeMVar >>= \res -> return ((mconcat res), g)
source share