tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

Descriptor.hs (1038B)


      1 -- Owned raw descriptors: a failed close must never be retried against a number
      2 -- the OS may already have recycled. No public descriptors or unrestricted FFI.
      3 module IOV2.Descriptor (closeOnce, releaseOnce, duplicateSync) where
      4 
      5 import Control.Exception (bracketOnError, mask_)
      6 import Control.Monad (when)
      7 import Data.IORef
      8 import GHC.IO.Handle (hDuplicate)
      9 import System.IO (Handle, hClose)
     10 import System.Posix.IO (closeFd, handleToFd)
     11 import System.Posix.Types (Fd)
     12 import System.Posix.Unistd (fileSynchronise)
     13 
     14 closeOnce :: Fd -> IO (IO ())
     15 closeOnce fd = releaseOnce (closeFd fd)
     16 
     17 -- Injectable action for close-failure/cancellation controls.
     18 releaseOnce :: IO () -> IO (IO ())
     19 releaseOnce action = do
     20   owned <- newIORef True
     21   pure $ mask_ $ do
     22     close <- atomicModifyIORef' owned (\old -> (False,old))
     23     when close action
     24 
     25 duplicateSync :: Handle -> IO (IO (), IO ())
     26 duplicateSync handle = mask_ $ do
     27   fd <- bracketOnError (hDuplicate handle) hClose handleToFd
     28   release <- closeOnce fd
     29   pure (fileSynchronise fd, release)