new files
This commit is contained in:
parent
3af7344581
commit
86c034bb8b
1364 changed files with 21352 additions and 0 deletions
|
|
@ -0,0 +1,112 @@
|
|||
import Control.Concurrent
|
||||
import Control.Monad -- needed for "forM", "forM_"
|
||||
|
||||
-- (workers working, workers done, workers total)
|
||||
type Workshop = MVar (Int, Int, Int)
|
||||
-- list of IO actions to be performed by one worker
|
||||
type Actions = [IO ()]
|
||||
|
||||
newWorkshop :: IO Workshop
|
||||
newWorkshop = newMVar (0, 0, 0)
|
||||
|
||||
-- check point: workers wait here for the other workers to
|
||||
-- finish, before resuming execution/restarting
|
||||
checkPoint :: Workshop -> IO ()
|
||||
checkPoint w = do
|
||||
(working, done, count) <- takeMVar w
|
||||
-- all workers are done: reset counters and return (threads
|
||||
-- resume execution or restart)
|
||||
if working <= 0 && done == count
|
||||
then do
|
||||
putStrLn "---- Check Point"
|
||||
putMVar w (0, 0, count)
|
||||
-- mvar was just initialized: do nothing, just return.
|
||||
-- otherwise, a race condition may arise
|
||||
else if working == 0 && done == 0
|
||||
then putMVar w (working, done, count)
|
||||
-- workers are still working: wait for them (loop)
|
||||
else do
|
||||
putMVar w (working, done, count)
|
||||
checkPoint w
|
||||
|
||||
-- join the workshop
|
||||
addWorker :: Workshop -> ThreadId -> IO ()
|
||||
addWorker w i = do
|
||||
(working, done, count) <- takeMVar w
|
||||
putStrLn $ "Worker " ++ show i ++ " has joined the group."
|
||||
putMVar w (working, done, count + 1)
|
||||
|
||||
-- leave the workshop
|
||||
removeWorker :: Workshop -> ThreadId -> IO ()
|
||||
removeWorker w i = do
|
||||
(working, done, count) <- takeMVar w
|
||||
putStrLn $ "Worker " ++ show i ++ " has left the group."
|
||||
putMVar w (working, done, count - 1)
|
||||
|
||||
-- increase the number of workers doing something.
|
||||
-- optionally, print a message using the thread's ID
|
||||
startWork :: Workshop -> ThreadId -> IO ()
|
||||
startWork w i = do
|
||||
(working, done, count) <- takeMVar w
|
||||
putStrLn $ "Worker " ++ show i ++ " has started."
|
||||
putMVar w (working + 1, done, count)
|
||||
|
||||
-- decrease the number of workers doing something and increase the
|
||||
-- number of workers done. optionally, print a message using
|
||||
-- the thread's ID
|
||||
finishWork :: Workshop -> ThreadId -> IO ()
|
||||
finishWork w i = do
|
||||
(working, done, count) <- takeMVar w
|
||||
putStrLn $ "Worker " ++ show i ++ " is ready."
|
||||
putMVar w (working - 1, done + 1, count)
|
||||
|
||||
-- put a worker to do his tasks. the steps are:
|
||||
-- 1. join the workshop "w"
|
||||
-- 2. report that the worker has started an action
|
||||
-- 3. perform one action
|
||||
-- 4. report that the worker is ready for the next action
|
||||
-- 5. wait for the other workers to finish
|
||||
-- 6. repeat from 2 until the worker has nothing more to do
|
||||
-- 7. leave the workshop
|
||||
worker :: Workshop -> Actions -> IO ()
|
||||
worker w actions = do
|
||||
i <- myThreadId
|
||||
addWorker w i
|
||||
forM_ actions $ \action -> do
|
||||
startWork w i
|
||||
action
|
||||
finishWork w i
|
||||
checkPoint w
|
||||
removeWorker w i
|
||||
|
||||
-- launch several worker threads. their thread ID's are returned
|
||||
shop :: Workshop -> [Actions] -> IO [ThreadId]
|
||||
shop w actions = do
|
||||
forM actions $ \x -> forkIO (worker w x)
|
||||
|
||||
main = do
|
||||
-- make a workshop
|
||||
w <- newWorkshop
|
||||
|
||||
-- the workers won't be doing anything special, just wait for n
|
||||
-- regular intervals. pids gathers the ID's of the threads
|
||||
|
||||
-- this are the first workers joining the workshop
|
||||
pids1 <- shop w
|
||||
[replicate 5 $ threadDelay 1300000
|
||||
,replicate 10 $ threadDelay 759191
|
||||
,replicate 7 $ threadDelay 965300]
|
||||
|
||||
-- wait for 5 secs before the next workers join
|
||||
threadDelay 5000000
|
||||
|
||||
-- these are other workers that join the workshop later
|
||||
pids2 <- shop w
|
||||
[replicate 6 $ threadDelay 380000
|
||||
,replicate 4 $ threadDelay 250000]
|
||||
|
||||
-- wait for a key press
|
||||
getChar
|
||||
|
||||
-- kill all worker threads before exit, if they're still running
|
||||
forM_ (pids1 ++ pids2) killThread
|
||||
Loading…
Add table
Add a link
Reference in a new issue