{-# 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
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
RawDirStream
dsHandle <- OsPath -> IO RawDirStream
Raw.openRawDirStream OsPath
root
Counter
dsIsClosed <- Int -> IO Counter
Counter.new Int
0
let result :: DirStream
result = DirStream{RawDirStream
dsHandle :: RawDirStream
dsHandle :: RawDirStream
dsHandle, Counter
dsIsClosed :: Counter
dsIsClosed :: Counter
dsIsClosed, Weak DirStream
dsFin :: Weak DirStream
dsFin :: Weak DirStream
dsFin}
Weak DirStream
dsFin <- DirStream -> DirStream -> Maybe (IO ()) -> IO (Weak DirStream)
forall k v. k -> v -> Maybe (IO ()) -> IO (Weak v)
mkWeak DirStream
result DirStream
result (IO () -> Maybe (IO ())
forall a. a -> Maybe a
Just (DirStream -> IO ()
closeDirStreamInternal DirStream
result))
DirStream -> IO DirStream
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure DirStream
result
closeDirStream :: DirStream -> IO ()
closeDirStream :: DirStream -> IO ()
closeDirStream DirStream
stream =
Weak DirStream -> IO ()
forall v. Weak v -> IO ()
finalize (DirStream -> Weak DirStream
dsFin 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
!Int
oldVal <- Counter -> Int -> Int -> IO Int
Counter.cas Counter
dsIsClosed Int
0 Int
1
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
oldVal Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
RawDirStream -> IO ()
Raw.closeRawDirStream RawDirStream
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