concurrency - How to use thread safe shared variables in Haskell -


iorefs, mvars, , tvars can used wrap shared variable in concurrent context. i've studied concurrent haskell while , i've encounted questions. after searching on stackoverflow , read through related question, questions not resolved.

  1. according ioref documentation,"extending atomicity multiple iorefs problematic", can explain why single ioref safe more 1 iorefs problematic?
  2. modifymvar "exception-safe, atomic if there no other producers mvar". see mvar's documentation. source code show modifymvar compose getmvar , putmvar sequencially, indicating it's note thread-safe if there producer. if there no producer , threads behave in "takemvar putmvar" way, thread-safe use modifymvar ?

to give concrete situation, i'll show actual problem. i've shared variables never empty , want them mutable states threads can simultaneously modify these variables.

ok, seems tha tvar solve clearly. i'm not satisfied , i'm eager answers questions above. appreciated.

-------------- re: @gabrielgonzalez bfs interface code ------------------

code below bfs interface using state monad.

{-# language typefamilies, flexiblecontexts #-}  module data.graph.par.class  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   type vertex g :: *   type edge g :: *    -- type path g :: *           -- useless   type vertexproperty g :: *   type edgeproperty g :: *   edges :: g -> io [edge g]   vertexes :: g -> io [vertex g]   adjacencies :: g -> vertex g -> io [vertex g]   vertexproperty :: vertex g -> g -> io (vertexproperty g)   edgeproperty :: edge g -> g -> io (edgeproperty g)   atomicmodifyvertexproperty :: (vertexproperty g -> io (vertexproperty g)) ->                                  vertex g -> g -> io (g a) -- fixed   spanforest :: pargraph g => [vertex g] -> statet (g a) io () spanforest roots = parallelise (map spantree roots) -- parallel version  spanforestseq :: pargraph g => [vertex g] -> statet (g a) io () spanforestseq roots = form_ roots spantree -- sequencial version  spantree :: pargraph g => vertex g -> statet (g a) io () spantree root = spantreeonestep root >>= \res -> case res of   [] -> return ()   adjs -> spanforestseq adjs  spantreeonestep :: pargraph g => vertex g -> statet (g a) io [vertex g] spantreeonestep v = statet $ \g -> adjacencies g v >>= \adjs -> return (adjs, g)  parallelise :: (pargraph g, monoid b) => [statet (g a) io b] -> statet (g a) io b parallelise [] = return mempty parallelise ss = syncgraphop $ map forkgraphop ss  forkgraphop :: (pargraph g, monoid b) => statet (g a) io b -> statet (g a) io (mvar b) forkgraphop t =    s <-   mv <- mapstatet (forkhelper s) t   return mv       forkhelper s x =       mv <- newemptymvar       forkio $ x >>= \(b, s) -> putmvar mv b       return (mv, s)  syncgraphop :: (pargraph g, monoid b) => [statet (g a) io (mvar b)] -> statet (g a) io b syncgraphop [] = return mempty syncgraphop ss = collectmvars ss >>= waitresults       collectmvars [] = return []     collectmvars (x:xs) =       mvx <- x       mvxs <- collectmvars xs       return (mvx:mvxs)     waitresults mvs = statet $ \g -> form mvs takemvar >>= \res -> return ((mconcat res), g) 

  1. modern processors offer compare-and-swap instruction atomically modifies single pointer. expect if track down deep enough, find instruction 1 used implement atomicmodifyioref. therefore easy provide atomic access single pointer. however, because there isn't such hardware support more 1 pointer, whatever need have done in software. typically involves inventing , manually enforcing protocol in threads -- complicated , error-prone.

  2. yes, if threads agree use "single takemvar followed single putmvar" behavior, modifymvar safe.


Comments

Popular posts from this blog

java - pagination of xlsx file to XSSFworkbook using apache POI -

Unlimited choices in BASH case statement -

apache - How do I stop my index.php being run twice for every user -