Implement System.timeoutWithUnmask as a way to document the deficiency of ordinary System.timeout
The goal is to document the unobvious problem that expressions like timeout 1000 takeMVar, when executed in a loop, lead to data loss. Namely, the IO action (consisting of takeMVar) may be interrupted just after takeMVar finishes and so consumes the value put into the MVar, giving Nothing as the result of the whole timeout expression. That's despite takeMVar being atomic and timeout being subtle and expensive. In the attached program around 15% of the data is lost with timeout 1 and -threaded for me.
This ticket is about implementing System.timeoutWithUnmask (sibling of forkIOwithUnmask), proposed by @duog, that prevents data loss in calls such as timeoutWithUnmask $ \_restore -> takeMVar mv. The documentation would point out the difference and suggest to switch to STM for a more extensible solution using registerDelay (see https://stackoverflow.com/questions/22171895/using-tchan-with-timeout/22182074). As suggested by @duog, the general usage pattern of timeoutWithUnmask would be timeoutWithUnmask $ \restore -> do { r <- restore $ expensive; cheap r; }.
Another angle is to implement tryTakeMVarWithTimeout and cross-reference explaining why flip timeout takeMVar is not equivalent by far.
Here's the file showing the data loss (and an occassional lock-up for an analogous reason): timeoutTest.hs