{-# 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
RawDirStream
dsHandle <- OsPath -> IO RawDirStream
Raw.openRawDirStream OsPath
root
Counter
dsIsClosed <- Int -> IO Counter
Counter.new Int
0
let stream :: DirStream
stream = 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
stream DirStream
stream (IO () -> Maybe (IO ())
forall a. a -> Maybe a
Just (DirStream -> IO ()
closeDirStreamInternal DirStream
stream))
DirStream -> IO DirStream
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure DirStream
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
!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