1 -----------------------------------------------------------------------------
3 -- Fast write-buffered Handles
5 -- (c) The University of Glasgow 2005-2006
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 )
29 import Control.Monad ( when )
30 import Data.Char ( ord )
34 import GHC.IOBase ( IO(..) )
35 import System.IO ( hPutBuf )
36 import GHC.Ptr ( Ptr(..) )
38 import GHC.Exts ( Int(..), Int#, Addr# )
40 -- -----------------------------------------------------------------------------
42 data BufHandle = BufHandle {-#UNPACK#-}!(Ptr Word8)
43 {-#UNPACK#-}!FastMutInt
46 newBufHandle :: Handle -> IO BufHandle
48 ptr <- mallocBytes buf_size
51 return (BufHandle ptr r hdl)
53 buf_size = 8192 :: Int
55 #define STRICT2(f) f a b | a `seq` b `seq` False = undefined
56 #define STRICT3(f) f a b c | a `seq` b `seq` c `seq` False = undefined
58 bPutChar :: BufHandle -> Char -> IO ()
60 bPutChar b@(BufHandle buf r hdl) c = do
63 then do hPutBuf hdl buf buf_size
66 else do pokeElemOff buf i (fromIntegral (ord c) :: Word8)
67 writeFastMutInt r (i+1)
69 bPutStr :: BufHandle -> String -> IO ()
71 bPutStr b@(BufHandle buf r hdl) str = do
74 where loop _ i | i `seq` False = undefined
75 loop "" i = do writeFastMutInt r i; return ()
78 hPutBuf hdl buf buf_size
81 pokeElemOff buf i (fromIntegral (ord c))
84 bPutFS :: BufHandle -> FastString -> IO ()
85 bPutFS b@(BufHandle buf r hdl) fs@(FastString _ len _ fp _) =
86 withForeignPtr fp $ \ptr -> do
88 if (i + len) >= buf_size
89 then do hPutBuf hdl buf i
92 then hPutBuf hdl ptr len
95 copyBytes (buf `plusPtr` i) ptr len
96 writeFastMutInt r (i+len)
98 bPutLitString :: BufHandle -> Addr# -> Int# -> IO ()
99 bPutLitString b@(BufHandle buf r hdl) a# len# = do
101 i <- readFastMutInt r
102 if (i+len) >= buf_size
103 then do hPutBuf hdl buf i
106 then hPutBuf hdl (Ptr a#) len
107 else bPutLitString b a# len#
109 copyBytes (buf `plusPtr` i) (Ptr a#) len
110 writeFastMutInt r (i+len)
112 bFlush :: BufHandle -> IO ()
113 bFlush b@(BufHandle buf r hdl) = do
114 i <- readFastMutInt r
115 when (i > 0) $ hPutBuf hdl buf i
120 myPutBuf s hdl buf i =
121 modifyIOError (\e -> ioeSetErrorString e (ioeGetErrorString e ++ ':':s ++ " (" ++ show buf ++ "," ++ show i ++ ")")) $