thread-hierarchy alternatives and similar packages
Based on the "Concurrency" category.
Alternatively, view thread-hierarchy alternatives based on common mentions on social networks and blogs.
haxl10.0 2.2 thread-hierarchy VS haxlA Haskell library that simplifies access to remote data, such as databases or web-based services.
streamly9.9 9.9 thread-hierarchy VS streamlyHigh performance, concurrent functional programming abstractions
async9.7 2.1 thread-hierarchy VS asyncRun IO operations asynchronously and wait for their results
concurrency9.5 1.7 thread-hierarchy VS concurrencySystematic concurrency testing meets Haskell.
async-dejafu9.5 1.7 thread-hierarchy VS async-dejafuSystematic concurrency testing meets Haskell.
lvish9.3 0.0 thread-hierarchy VS lvishThe LVish Haskell library
chaselev-dequeA collection of different packages for CAS based data structures.
unagi-chan9.2 0.0 thread-hierarchy VS unagi-chanA haskell library implementing fast and scalable concurrent queues for x86, with a Chan-like API
mvc9.0 0.0 thread-hierarchy VS mvcModel-view-controller
lifted-threadslifted IO operations from the threads library
fraxl8.9 0.0 thread-hierarchy VS fraxlCached and parallel data fetching.
capataz8.7 0.0 thread-hierarchy VS capatazOTP-like supervision trees in Haskell
stm-containersContainers for STM
consumers8.7 0.0 thread-hierarchy VS consumersConcurrent PostgreSQL data consumers
pipes-concurrencyConcurrency for the pipes ecosystem
stm-conduit8.5 0.0 thread-hierarchy VS stm-conduitSTM-based channels for conduits.
scheduler8.5 0.0 thread-hierarchy VS schedulerA work stealing scheduler
ki8.4 7.4 thread-hierarchy VS kiA lightweight, structured concurrency library
libcspm8.2 0.0 thread-hierarchy VS libcspmThe library FDR3 uses for parsing, type checking and evaluating machine CSP.
cspmchecker8.2 0.0 thread-hierarchy VS cspmcheckerThe library FDR3 uses for parsing, type checking and evaluating machine CSP.
lifted-async8.1 0.0 thread-hierarchy VS lifted-asyncRun lifted IO operations asynchronously and wait for their results
flush-queue8.1 0.0 thread-hierarchy VS flush-queue...
threads7.9 0.0 thread-hierarchy VS threadsFork threads and wait for their result
speculation7.8 0.0 thread-hierarchy VS speculationSafe, programmable, speculative evaluation for Haskell
legionDistributed, stateful, homogeneous microservice framework.
promises7.5 0.0 thread-hierarchy VS promiseslazy promises
stm-queue-extrasExtra utilities for STM queues
threads-supervisorSimple, IO-based Haskell library for Erlang-inspired thread supervisors
concurrent-machinesConcurrency features for the Haskell machines package
concurrent-extraExtra concurrency primitives
immortal7.3 0.0 thread-hierarchy VS immortalSpawn threads that never die (unless told to do so)
concurrent-supplyA fast globally unique variable supply with a pure API
lukko6.7 0.0 thread-hierarchy VS lukkoFile locking
sirkel6.7 0.0 thread-hierarchy VS sirkelSirkel; a Chord DHT in haskell. Node failure, replication and batteries included!
unbounded-delaysUnbounded thread delays and timeouts
slave-thread6.6 2.9 thread-hierarchy VS slave-threadA principal solution to ghost threads and silent exceptions
thread-supervisorA simplified implementation of Erlang/OTP like supervisor for GHC thread
atomic-modifyIncubator for my Haskell libraries
timers6.2 0.0 thread-hierarchy VS timersSimple package that implements timers. Both "one-shot" and "repeating" timers are implemented.
split-channelControl.Concurrent.Chan split into sending and receiving halves.
mvc-updates6.1 0.0 thread-hierarchy VS mvc-updatesConcurrent and combinable updates
token-bucket6.1 0.0 thread-hierarchy VS token-bucketHaskell rate limiter library using lazy token bucket algorithm
concurrent-hashtableA thread-safe hash table in Haskell
ctrie6.0 0.0 thread-hierarchy VS ctrieNon-blocking concurrent hashmap for Haskell
unagi-bloomfilterA fast, cache-efficient, concurrent bloom filter in Haskell
threadmanagerSimple thread management
unique5.9 0.0 thread-hierarchy VS uniquefast unique variables
kickchan5.8 0.0 thread-hierarchy VS kickchanBounded channels with invalidating readers
Static code analysis for 29 languages.
Do you think we are missing an alternative of thread-hierarchy or a related project?
Managing Haskell threads in hierarchical manner.
This package provides parent-child association and guaranteed clean-up of children over plain Haskell thread. You can terminate all child threads and grand child threads by just killing their parent thread.
Unlike Unix process, plain Haskell thread, created by forkIO, has no parent-child relation each other. This means termination of parent thread doesn't result its children also terminated. This is good design as a low level API because it gives user greatest flexibility. However, it also means managing entire lifecycle of thread is totally a responsibility of user.
Here one thing you need to be aware. Garbage collection doesn't work on living thread. When you lost reference to an object, garbage collector frees up the object for you. However, even though you lost the thread ID of your child thread, Haskell runtime doesn't consider the thread is orphaned. The child thread continue running.
This is prone to create thread leakage. You can accidentally lose thread ID of child thread by crash of parent thread. Now you no longer have way to kill orphaned child thread. This is thread leakage.
The low level forkIO API requires you keep track and manage entire thread lifecycle including accidental case like the above. Hand crafting it might be painful.
This package is intended to provide simple replacement API over plain forkIO in case of when all you need to do on parent termination is just terminating all its children.
If you need to keep your child running after parent terminated, this API is not for you.
Why not withAsync?
The typical use case for this package is TCP server style use case. In such use case, you have to create virtually infinite number of threads and they finish in random timing but you are not so interested in their return value.
withAsync coming with
async package solves different problem than this package.
It is good for taking actions asynchronously but eventually you need their return values.
Or, even you aren't care of return values, you only need to take several finite number of
Bellow explains why
withAsync is not good for managing large number of threads.
withAsync is essentially a sugar over bracket pattern like this.
withAsync action inner = bracket (async action) uninterruptibleCancel inner
uninterruptibleCancel to the
action is executed on asynchronous exception
at parent thread where withAsync itself is living. However it also guarantees the
is executed on normal exit from
inner too. Thus, the
action can only live within the
lifecycle of the
withAsync call. If you want to keep your
action alive, you have to
inner continue running until your
So, what if let async action go and make recursive call form
inner back to your loop?
It is a bad idea. Because
withAsync is a
bracket, recursive call from
In other words, the difference between
newChild is strategy of un-installing
withAsync uninstalls its cleanup handler based on its lexical scope.
newChild uninstalls it based on actual dynamic thread termination.
Almost all you need to know is one data type and one function:
Threads created by
newChild guarantee automatic cleanup on its exit
regardless normal exit or cancellation by asynchronous exception.
In order to that works properly, user must ensure following rules.
- User provided thread handler must accept
ThreadMapas its first argument.
- When the user provided handler creates its child thread, it must use newChild with given
- For 1st thread you create by newChild, give it a
ThreadMap is house-keeping object for your thread. It is a mutable map keeping track
living child threads of your thread. When your thread handler started, you receives
ThreadMap via 1st argument of your handler. When you create a child thread
of your thread,
newChild automatically update (mutate) your
ThreadMap by adding
newly created child thread. When your child thread terminated, it is automatically removed
Same manner is applied to child thread and grandchild thread as long as you follow the rule the above.
How it works
newChild creates a new thread, it installs two cleanup tasks for you.
- Killing all thread contained in
ThreadMapof the new thread. It kills all children of the new thread.
- Removing the new thread itself from parent's
The cleanup tasks are called when the new thread exit normally or terminated by asynchronous exception. By this mechanism, termination of top level thread is propagated down to all its children, children of children, and so on.
When you create the first thread managed by this module, create a new empty
ThreadMap then call
newChild with it. The newCall automatically install cleanup routine to the handler you provided.
createRootThread :: IO ThreadId createRootThread = do rootThreadMap <- newThreadMap threadID <- newChild rootThreadMap rootThreadHandler return threadID
When a thread managed by this module creates its child thread, call newChild with
received via handlers argument.
rootThreadHandler :: ThreadMap -> IO () rootThreadHandler myChildrenThreadMap = do void $ newChild myChildrenThreadMap $ \grandChildrenThreadMap -> do yourCode return ()
You can install your own cleanup routine using finally or both resource acquisition and cleanup routine using bracket.
-- Forking a new child with your own cleanup void $ newChild childrenOfCurrentThread $ \childrenOfHandler -> yourThreadHandler `finally` yourCleanupRoutine -- Forking a new child with resource acquisition and cleanup void $ newChild childrenOfCurrentThread $ \childrenOfHandler -> bracket yourResourceAcquiringRoutine yourCleanupRoutine yourThreadHandler
Currently, unlike async function, this module is not designed to back any return value from child thread to parent thread. This module focuses on guaranteed cleanup on thread termination.
*Note that all licence references and agreements mentioned in the thread-hierarchy README section above are relevant to that project's source code only.