Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A function to wait for slaves without forking a new thread #4

Open
neongreen opened this issue Sep 29, 2016 · 8 comments
Open

A function to wait for slaves without forking a new thread #4

neongreen opened this issue Sep 29, 2016 · 8 comments

Comments

@neongreen
Copy link

I miss it every time I use slave-thread. I end up doing this:

main = fork $ do
  ... run some slave threads ...
  forever $ threadDelay 1000000
@nikita-volkov
Copy link
Owner

What you need is the semaphore idiom.

main = 
  fork $ do
    semaphore <- newEmptyMVar
    fork $ do
      -- Do things
      -- ...
      -- Release the semaphore
      putMVar semaphore ()
    -- Block until semaphore is filled with value
    takeMVar semaphore

For more complicated cases I recommend looking at libraries like "SafeSemaphore".

@neongreen
Copy link
Author

neongreen commented Sep 29, 2016

I have several forked threads inside main, though. Should I just use a multisemaphore or something? (Does such a thing even exist?) Also, I don't see why it couldn't be exported from slave-thread given that it's already a part of slave-thread and it's useful – perhaps I'm missing something and the semaphore approach is better than the waitForSlaves approach?

@nikita-volkov
Copy link
Owner

nikita-volkov commented Sep 29, 2016

Probably such a function would be a useful addition. I don't think I'll implement it myself any time soon, however I would accept a PR.

given that it's already a part of slave-thread and it's useful

I'm not sure what you're referring here to.

Should I just use a multisemaphore or something?

For now you can declare a semaphore per thread (or wrap it in a utility function). Or use a counting semaphore from the mentioned library.

@nikita-volkov
Copy link
Owner

A utility function could look like this:

forkWait :: IO () -> IO (IO ())
forkWait io =
  do
    semaphore <- newEmptyMVar
    fork $ do
      io
      putMVar semaphore ()
    return (takeMVar semaphore)

To be used like this:

main = 
  fork $ do
    wait1 <-
      forkWait $ do
        -- Do things
        -- ...
    wait2 <-
      forkWait $ do
        -- Do things
        -- ...
    wait1
    wait2

@neongreen
Copy link
Author

I'm not sure what you're referring here to.

slave-thread uses waitForSlavesToDie internally. I'm not sure if it's exactly what is needed, though (perhaps there should be some exception handling added?).

@nikita-volkov
Copy link
Owner

nikita-volkov commented Sep 29, 2016

slave-thread uses waitForSlavesToDie internally

It's a different thing. It ensures that the slaves are dead before the finaliser of the master is executed. The slaves still get killed when the master dies. Brutal, I know :)

@mitchellwrosen
Copy link
Contributor

@neongreen How about an Async-like abstraction? (It might be a useful addition to this library, but it's very simple to implement):

data Async a
  = Async ThreadId (STM a)

async :: IO a -> IO (Async a)
async computation = do
  result <- newEmptyTMVarIO
  thread <- fork (computation >>= atomically . putTMVar result)
  return (Async thread (readTMVar result))

wait :: Async a -> STM a
wait (Async _ computation) = computation

cancel :: Async a -> IO ()
cancel (Async thread _) = killThread thread

Note that this still has the SlaveThread semantics of, if a slave fails, everything comes crashing down. This is unlike async, which gives you a way of checking a forked thread's success or failure with waitCatch :: Async a -> IO (Either SomeException a)

@mitchellwrosen
Copy link
Contributor

Oh, but if you just want all slaves to finish, but don't want to keep track of each of them (like with an Async thing), then I agree waitForSlavesToDie would suffice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants