-
-
Notifications
You must be signed in to change notification settings - Fork 22
add TQueue/TBQueue example #18
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
Conversation
|
Hey this is an interesting use of a bounded queue! We've done some revision to make this more concise:
{-# LANGUAGE NumericUnderscores #-}
module Main where
import Control.Concurrent
import Control.Concurrent.Async
import Control.Concurrent.STM
import Control.Exception.Safe
import System.IO
import System.Random
-- Let's pretend we will make making many requests to some vendor's API,
-- and the vendor may block us if we make too many simultaneous requests.
vendorApiCall :: Int -> IO Int
vendorApiCall n =
do
t <- getStdRandom (randomR (500_000, 1_500_000))
threadDelay t
return (n * n)
main :: IO ()
main =
do
hSetBuffering stdout LineBuffering
-- This bounded queue can contain only five elements. Each request will
-- begin by adding an element onto the queue and end by removing an
-- element from the queue, thus ensuring that no more than five tasks
-- can ever be running at once.
bq <- atomically (newTBQueue 5)
let
acquire = atomically (writeTBQueue bq ())
release = atomically (readTBQueue bq)
-- `forConcurrently_` is just like `for_`, but concurrent.
forConcurrently_ [1 .. 10] $ \x ->
bracket_ acquire release $
do
putStrLn ("start: " ++ show x)
result <- vendorApiCall x
putStrLn ("finish: " ++ show x ++ ", result: " ++ show result)What do you think, is it still clear enough? This'll be released under the creative commons CC BY-NC 4.0 license - Please let us know if that's okay and how you'd like to be attributed. |
|
@chris-martin , you almost completely change my example, so surely I'm okay with suggested license. :) |
|
We can update the code after we merge, either way's fine. Sure we shuffled a lot around but having the starting point to work with is huge :) Is "Dima Kurilo" the name we should attach to it? (we can link to a blog or twitter account or something too if you'd like) I perpetually struggle with how much "magic" to include, trying to find the right balance between fundamentals and my presumed readers' impatience. Getting familiar with a set of primitives is a real source of comfort, but if we eschew conveniences that are commonplace in other languages, then that can lead authors down a road that makes Haskell seem way harder than other languages in places where it doesn't need to be. The Phrasebook in particular is an intentional departure from our usual impulses and we're trying to err on the side of giving readers quick easy answers, as long as the things we're recommending are still very generally useful (and I believe In this case I think it also really comes down to trying to present one small topic at a time; worrying about how to fork and join threads was distracting while what we were trying to think about was queues. The topics 1. forking/joining and the concept of blocking threads; and 2. exception handling; would make great separate pages with more room to show how to do more things from primitives. |
|
Great! Thank you. |
Fixes #14
I hope it's good enough.
In case I did it not clear enough, write me, please.