I've been asking a few questions about concurrency in Haskell, particular TVar
, and I've had concerns about livelock with TVar
.
Instead, I've proposed this solution.
(1) Wrap all shared data in the program in one data structure, and wrap that in an IORef
.
(2) Simply do any changes using atomicModifyIORef
.
I believe this prevents both deadlocks and livelocks (whereas TVar only prevents the former). Also, because atomicModifyIORef
simply links another thunk into a chain (which is a couple of pointer operations) this is not a bottl neck. All of the actual operations on the data can be done in parallel, as long as they do not mutually depend on each other. The Haskell runtime system will work this out.
I however feel like this is too simple. Are there any "gotchas" I've missed?
Well, it's not going to compose well. And serializing all of your shared memory modifications through a single IORef will mean that only one thread will be able to modify shared memory at a time, all you've really done is made a global lock. Yes it will work, but it will be slow and nowhere near as flexible as TVars or even MVars.