multithreading - How does one atomically use a set of handles? -
let's have program bunch of threads. 1 thread freeze access stdin, stdout, , stderr (causing other threads or keyboards block until done) output doesn't interweaved them. there way directly, or there have manager thread, know, managin' handle. relatedly, cause input on stdin block output on stdout until received , handled (atomically)?
you can simulate lock controlling access resource mvar. aquire lock taking value takemvar , release lock replacing value putmvar. example, can define following
import control.concurrent import control.concurrent.mvar main = stdinlock <- newmvar () -- create new lock stdin (unaquired) let printwithlabel b = takemvar stdinlock -- aquire lock stdin putstrln (show ++ ":") print b putmvar stdinlock () -- release lock stdin actions = map fork $ zipwith printwithlabel [1..26] ['a'..] donesignals <- sequence actions sequence donesignals return () fork :: io -> io (io ()) fork = done <- newemptymvar forkio (a >> putmvar done ()) return (takemvar done) we extract locking functionality function
withlock :: mvar () -> io -> io withlock lock action = takemvar lock x <- action putmvar lock () return x withlock performs io action after acquiring lock , releases when done. doesn't handle if code throws exceptions , notably not release lock if exception thrown. lock in concurrent-extra provides similar helper function brackets operation (handling exceptions) acquiring , releasing lock.
in terms of lock , async above example can simplified to
import qualified control.concurrent.lock lock import control.concurrent.async main = stdinlock <- lock.new let printwithlabel b = lock.with stdinlock $ putstrln (show ++ ":") print b actions = zipwith printwithlabel [1..26] ['a'..] donesignals <- mapm async actions mapm_ wait donesignals if want thread reading input on stdin block output other threads stdout can use single lock control both stdin , stdout.
Comments
Post a Comment