1 -----------------------------------------------------------------------------
3 -- Fast write-buffered Handles
5 -- (c) The University of Glasgow 2005
7 -- This is a simple abstraction over Handles that offers very fast write
8 -- buffering, but without the thread safety that Handles provide. It's used
9 -- to save time in Pretty.printDoc.
11 -----------------------------------------------------------------------------
23 #include "HsVersions.h"
27 import Panic ( panic )
34 #if __GLASGOW_HASKELL__ < 503
35 import PrelIOBase ( IO(..) )
36 import IOExts ( hPutBufFull )
38 import GHC.IOBase ( IO(..) )
39 import System.IO ( hPutBuf )
42 import GLAEXTS ( touch#, byteArrayContents#, Int(..), Int#, Addr# )
44 import PrimPacked ( Ptr(..) )
46 -- -----------------------------------------------------------------------------
48 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
49 {-#UNPACK#-}!FastMutInt
52 newBufHandle :: Handle -> IO BufHandle
54 ptr <- mallocBytes buf_size
57 return (BufHandle ptr r hdl)
59 buf_size = 8192 :: Int
61 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
62 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
64 bPutChar :: BufHandle -> Char -> IO ()
66 bPutChar b@(BufHandle buf r hdl) c = do
69 then do hPutBuf hdl buf buf_size
72 else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
73 writeFastMutInt r (i+1)
75 bPutStr :: BufHandle -> String -> IO ()
77 bPutStr b@(BufHandle buf r hdl) str = do
80 where loop _ i | i `seq` False = undefined
81 loop "" i = do writeFastMutInt r i; return ()
84 hPutBuf hdl buf buf_size
87 pokeElemOff buf i (fromIntegral (ord c))
90 bPutFS :: BufHandle -> FastString -> IO ()
91 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len# arr#) = do
94 if (i + len) >= buf_size
95 then do hPutBuf hdl buf i
99 let a# = byteArrayContents# arr#
100 hPutBuf hdl (Ptr a#) len
104 let a# = byteArrayContents# arr#
105 copyBytes (buf `plusPtr` i) (Ptr a#) len
107 writeFastMutInt r (i+len)
108 bPutFS _ _ = panic "bPutFS"
110 bPutLitString :: BufHandle -> Addr# -> Int# -> IO ()
111 bPutLitString b@(BufHandle buf r hdl) a# len# = do
113 i <- readFastMutInt r
114 if (i+len) >= buf_size
115 then do hPutBuf hdl buf i
118 then hPutBuf hdl (Ptr a#) len
119 else bPutLitString b a# len#
121 copyBytes (buf `plusPtr` i) (Ptr a#) len
122 writeFastMutInt r (i+len)
124 bFlush :: BufHandle -> IO ()
125 bFlush b@(BufHandle buf r hdl) = do
126 i <- readFastMutInt r
127 when (i > 0) $ hPutBuf hdl buf i
131 touch r = IO $ \s -> case touch# r s of s -> (# s, () #)
134 myPutBuf s hdl buf i =
135 modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $