Is there any known implementation of Haskell MVar in C? There is an example on how to implement it in C++. But, I will like to implement it in C – let us say only MVar CInt equivalent in C for now. Writing synchronization primitives can be tricky. So, I will like to avoid duplication of effort if someone has already done it. I didn’t understand the C++ example above well enough to confidently translate it into C – it hides the algorithmic details very well from my C++-inexperienced mind 🙂
The reason I am thinking about writing MVar in C is because it makes it really easy for me to use the FFI binding to an external C library to get the stream of data, and use Haskell threads to grab the data (from Storable vectors to avoid marshaling the data – MVar CInt here stores how much of the Storable vectors have been filled). I need to make sure that C threads writing to Storable locations are blocked while a Haskell thread is reading the data. That is where MVar synchronization on C side helps. It is also much faster to call unsafe or even safe C function from Haskell (~15ns for unsafe, ~150ns for safe in my test), than callback into Haskell from C (~5us). If callbacks were fast, I would have had C function call back into Haskell instead, and block on Haskell MVar.
Update:
Algorithm in pseudo-code will do as well. It should be quite easy to implement it in C, given the algorithm for newEmptyMVar, takeMVar and putMVar.
MVar can be implemented in C using a struct like below:
put_condis used by threads that put values in MVar to signal other threads that are waiting to take value from MVar.take_condis the analogous counterpart for take. As for scheduling, it is default scheduling.valueis a void pointer – so, the above structure can be used to protect any type of value in an MVar – of course, C will let you write that pointer outside MVar – so, it is the program’s responsibility to ensure this doesn’t happen (by avoiding squirreling awayvaluepointer outside MVar – always access it through MVar functions).Initializing
MVar:Empty
MVar– uses above function:putMVar:takeMVar:Complete code is on github, with example which shows how to use MVar.
MVar is quite fast if there is only one thread accessing it (and heavy contention). But, under heavy contention, and multiple threads (even two), it scales very poorly. This is not a surprise because of the way pthreads work. I have found MVar in Haskell to be very good with multiple threads. This is not a surprise given how well lightweight threads and concurrency primitives are implemented in GHC.