{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE UnboxedTuples #-}
module System.Directory.OsPath.Streaming.Internal
( DirStream(..)
, openDirStream
, readDirStream
, closeDirStream
, readDirStreamWithCache
) where
import Control.Concurrent.Counter (Counter)
import qualified Control.Concurrent.Counter as Counter
import Control.Monad (when)
import System.Mem.Weak (Weak, mkWeak, finalize)
import System.OsPath (OsPath)
import qualified System.Directory.OsPath.Streaming.Internal.Raw as Raw
import System.Directory.OsPath.Types
import System.Directory.OsPath.Utils (touch)
data DirStream = DirStream
{ DirStream -> RawDirStream
dsHandle :: !Raw.RawDirStream
, DirStream -> Counter
dsIsClosed :: {-# UNPACK #-} !Counter
, DirStream -> Weak DirStream
dsFin :: {-# UNPACK #-} !(Weak DirStream)
}
openDirStream :: OsPath -> IO DirStream
openDirStream :: OsPath -> IO DirStream
openDirStream OsPath
root = mdo
dsHandle <- OsPath -> IO RawDirStream
Raw.openRawDirStream OsPath
root
dsIsClosed <- Counter.new 0
let stream = DirStream{RawDirStream
dsHandle :: RawDirStream
dsHandle :: RawDirStream
dsHandle, Counter
dsIsClosed :: Counter
dsIsClosed :: Counter
dsIsClosed, Weak DirStream
dsFin :: Weak DirStream
dsFin :: Weak DirStream
dsFin}
dsFin <- mkWeak stream stream (Just (closeDirStreamInternal stream))
pure stream
closeDirStream :: DirStream -> IO ()
closeDirStream :: DirStream -> IO ()
closeDirStream DirStream
stream = do
Weak DirStream -> IO ()
forall v. Weak v -> IO ()
finalize (DirStream -> Weak DirStream
dsFin DirStream
stream)
DirStream -> IO ()
forall x. x -> IO ()
touch DirStream
stream
closeDirStreamInternal :: DirStream -> IO ()
closeDirStreamInternal :: DirStream -> IO ()
closeDirStreamInternal DirStream{RawDirStream
dsHandle :: DirStream -> RawDirStream
dsHandle :: RawDirStream
dsHandle, Counter
dsIsClosed :: DirStream -> Counter
dsIsClosed :: Counter
dsIsClosed} = do
!oldVal <- Counter -> Int -> Int -> IO Int
Counter.cas Counter
dsIsClosed Int
0 Int
1
when (oldVal == 0) $
Raw.closeRawDirStream dsHandle
readDirStream :: DirStream -> IO (Maybe (OsPath, FileType))
readDirStream :: DirStream -> IO (Maybe (OsPath, FileType))
readDirStream = RawDirStream -> IO (Maybe (OsPath, FileType))
Raw.readRawDirStream (RawDirStream -> IO (Maybe (OsPath, FileType)))
-> (DirStream -> RawDirStream)
-> DirStream
-> IO (Maybe (OsPath, FileType))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DirStream -> RawDirStream
dsHandle
readDirStreamWithCache
:: Raw.DirReadCache
-> DirStream
-> IO (Maybe (OsPath, Basename OsPath, FileType))
readDirStreamWithCache :: DirReadCache
-> DirStream -> IO (Maybe (OsPath, Basename OsPath, FileType))
readDirStreamWithCache DirReadCache
cache =
DirReadCache
-> RawDirStream -> IO (Maybe (OsPath, Basename OsPath, FileType))
Raw.readRawDirStreamWithCache DirReadCache
cache (RawDirStream -> IO (Maybe (OsPath, Basename OsPath, FileType)))
-> (DirStream -> RawDirStream)
-> DirStream
-> IO (Maybe (OsPath, Basename OsPath, FileType))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DirStream -> RawDirStream
dsHandle