ki/README.md

61 lines
1.9 KiB
Markdown
Raw Normal View History

2020-05-15 02:24:09 +03:00
`ki` is a lightweight structured-concurrency library inspired by
2020-05-14 17:31:57 +03:00
[libdill](http://libdill.org/), [trio](https://github.com/python-trio/trio),
and [golang.org/pkg/context](https://golang.org/pkg/context/).
The primary abstraction is the *scope*, which delimits the lifetime of *threads*
forked within it.
```haskell
2020-05-15 02:05:27 +03:00
-- Create a new scope
2020-05-14 17:31:57 +03:00
scoped :: Context -> (Scope -> IO a) -> IO a
2020-05-15 02:05:27 +03:00
-- Fork a thread within a scope
2020-05-14 17:31:57 +03:00
async :: Scope -> (Context -> IO a) -> IO (Thread a)
```
```haskell
2020-05-15 02:24:09 +03:00
Ki.scoped context \scope -> do
2020-05-14 17:31:57 +03:00
-- Fork three worker threads
2020-05-15 02:24:09 +03:00
Ki.async_ scope worker1
Ki.async_ scope worker2
Ki.async_ scope worker3
2020-05-14 17:31:57 +03:00
-- Block until either:
-- * They all finish successfully
-- * One throws an exception
-- * Someone throws an asynchronous exception to us
2020-05-15 02:24:09 +03:00
Ki.wait scope
2020-05-14 17:31:57 +03:00
```
A *scope* can be hard-cancelled: when the callback provided to `scoped` returns,
all remaining *threads* forked within it are killed. By the time `scoped` itself
returns, they're guaranteed to have finished.
A *scope* can be soft-cancelled, too, but it requires cooperation. A *thread*
can observe whether it's meant to gracefully terminate, but it may never notice,
or ignore the suggestion.
2020-05-15 02:05:27 +03:00
```haskell
-- Should I finish up?
cancelled :: Context -> IO Bool
```
2020-05-14 17:31:57 +03:00
```haskell
2020-05-15 02:24:09 +03:00
Ki.scoped context \scope -> do
2020-05-14 17:31:57 +03:00
-- Fork a worker thread
2020-05-15 02:24:09 +03:00
Ki.async_ scope worker
2020-05-14 17:31:57 +03:00
-- Signal soft-cancellation, and block until either:
-- * It finishes, either successfully or by throwing an exception
-- * Someone throws an asynchronous exception to us
-- * 1 second elapses
2020-05-15 02:24:09 +03:00
Ki.waitFor scope 1000000
2020-05-14 17:31:57 +03:00
```
Soft-cancellation is hierarchical: it is observable by all *threads* forked
2020-05-15 02:05:27 +03:00
within a *scope*, all *threads* _forked by_ them, and so on.
2020-05-14 17:31:57 +03:00
The implementation is tested for deadlocks, race conditions, and other
concurrency anomalies by [dejafu](http://hackage.haskell.org/package/dejafu), a
fantastic unit-testing library for concurrent programs.