-
Notifications
You must be signed in to change notification settings - Fork 12
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
Concurrency primitimes and thread safety #34
Comments
Another problem with the greatEscape :: IO ()
greatEscape = do
hSetBuffering stdout LineBuffering
res <- runEff . runConcurrent $ do
_ <- async $ do
liftIO $ forever do
print "still alive"
threadDelay 2_000
return "eff done"
print res
threadDelay 10_000 This is mentioned in the documentation, but I don't think it's necessary as a primitive, it can be done with Speaking of which, I did some experiments with Ki. The Naive version just exposes that this is This is my current best idea, with explicit |
Thanks! I have some ideas forthcoming about structured concurrency in Bluefin which give thread safety by construction, so watch this space. I have some concerns about the ki API, but think I have worked out how to make it type safe with Bluefin. |
Oh, for the record, this doesn't with my wrapper. useFile = runEff \io -> do
runScope io \scope -> do
_ <- BIO.withFile io "/dev/null" WriteMode \h -> do
_ <- forkWithNewEff scope do
BIO.hPutStr h "foo"
-- • Ambiguous type variable ‘forkEs0’ arising from a use of ‘BIO.hPutStr’
-- prevents the constraint ‘(e2 :> forkEs0)’ from being solved.
pure ()
pure () But to be fair, nothing works. Anyway looking forward to what is cooking! |
You can have a look at branch The thread safety story is this:
If you're feeling adventurous you might want to check it out. I envisage writing up a better explanation over the coming weeks. |
By the way, with the inclusion of the "well-scoped |
Thanks! I did some shallow dive. Double scope ("scope" is becoming a bit overloaded term, I blame Ki tho, nursery might be a better term) tag is a nice trick. I'll check a few things over time. I don't know if I should comment on the WIP code, but two things immediately came to mind.
impure :: Bool
impure = runPureEff $ do
evalState (0 :: Integer) $ \s -> do
scoped $ \scope -> do
t1 <- fork scope $ \excl1 -> do
let x = sum [1 .. 9_999_999] -- long op
exclusively excl1 $ do
put s x
put s 1
t2 <- fork scope $ \excl2 -> do
let x = sum [1 .. 9_999_999] -- long op
exclusively excl2 $ do
put s x
put s 2
_ <- awaitEff t1
_ <- awaitEff t2
pure ()
res <- get s
return $ res > 1
λ> filter (==True) . map (\_ -> impure) $ [1..10]
[True,True,True,True,True,True,True,True,True,True]
λ> :r
Ok, two modules loaded.
λ> filter (==True) . map (\_ -> impure) $ [1..10]
[]
I like it, because it is a handle, which goes with the spirit of the library. |
Oh, that's really interesting. I hadn't spotted you could get impurity arising from non-determinism of operation lengths. Thanks for pointing that out!
Probably best to leave more thoughts here, as the branch will be changing a lot, and be force-rebased, etc.. |
OK, bluefin/bluefin-internal/src/Bluefin/Internal/Concurrent.hs Lines 55 to 71 in 409f8e3
What were you imagining for |
While we cannot guarantee purity with sharing arbitrary effects across threads boundaries, it is not all that useless to try to make a pure interface for threading. There is some, ehm, prior art. It was all the rage back in the day :) We could even fix some deficiencies. I imagine Now, my name is not Simon, so it is probably broken in a few unparalleled ways, but it is a start. I did some simple benchmarks too, and we are on par with monad-par (pardon!).
The main benefit of adding I propose this: if you are interested, I can open a new issue about this, and we will leave this thread for concurrent primitives. Parallel stuff could be added later (there is an easy parallel pun awaiting here, but I have resisted). |
Oh nice, yes, I'm interested, so please start that new issue! |
We don't have any Bluefin-specific concurrency primitives and just rely on
MonadUnliftIO
to give us access toIO
currency primitives. This seems dangerous, firstly in light of #29, but also because we could actually use Bluefin's type system to forbid thread-unsafe access to resources.By way of comparison, effectful seems fairly lax. See haskell-effectful/effectful#292.
The text was updated successfully, but these errors were encountered: