Communicating with a long running concurrent thread

I usually reach for the STM very quickly, because it is just super convenient.

In your particular case, you probably want at least a thread per download, that handles the actual downloading. You need some kind of shared data structure that will hold meta-information (at least download url, start of download, length of downloaded data, and the Maybe (download result)).

If that is the case, then MVars sound like a great fit.

Then there is the question of how to start downloads and keep track of all of them. I would do something like that :

data DownloadInfo = ...

startDownload' :: Url -> IO (ThreadID, MVar DownloadInfo)
startDownload' url = do
    downloadinfo <- newMVar (DownloadInfo url 0 ...)
    tid <- forkIO (download url downloadinfo)
    return (downloadinfo, tid)

startDownload :: MVar (M.Map Url (ThreadID, MVar DownloadInfo) )
              -> Url
              -> IO ()
startDownload downloads url = do
    i <- startDownload' url
    modifyMVar_ (return . M.insert url i)

(Of course you probably will want to check if you are overwriting some data in the last line).

That way you can run startDownload from any thread. You can then check on your downloads with readMVar, and each details with a subsequent readMVar. You won't have any conflicts unless many threads start downloading at the same time.

You don't need bidirectional messaging, but perhaps I did not understand your use case properly and you actually need it ...

/r/haskell Thread Parent