-- | Internal mutex system to be used as long as the ViennaRNA package is not
-- thread-safe.

module BioInf.ViennaRNA.Internal
  ( viennaRNAmutex
  , withMutex
  , unsafePerformIO
  ) where

import Control.Concurrent.MVar (MVar, newMVar, withMVar, takeMVar, putMVar)
import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO)
import Debug.Trace

-- | The mutex guarding single-threaded access to the @ViennaRNA@ bindings as
-- long as the @C@ library is not multi-threaded.

viennaRNAmutex  MVar ()
viennaRNAmutex = unsafePerformIO $! newMVar ()
{-# NoInline viennaRNAmutex #-}

-- | Work with the ViennaRNA mutex.
--
-- This version seems strict enough to not block indefinitely.

withMutex  IO a  IO a
withMutex f = do
  ()  takeMVar viennaRNAmutex
  !x  f
  putMVar viennaRNAmutex ()
  return $! x
{-# NoInline withMutex #-}