Z-IO 0.6.1.0 → 0.6.2.0
raw patch · 12 files changed
+615/−456 lines, 12 filesdep +criteriondep +microlensdep ~Z-Datadep ~basedep ~containersnew-component:exe:z-io-http-benchPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: criterion, microlens
Dependency ranges changed: Z-Data, base, containers, exceptions, stm, time, unordered-containers
API changes (from Hackage documentation)
- Z.IO.FileSystem.Watch: watchDirsRecursively :: [CBytes] -> IO (IO (), IO (Source FileEvent))
- Z.IO.Logger: Logger :: (Builder () -> IO ()) -> IO () -> IO () -> IO (Builder ()) -> LogFormatter -> {-# UNPACK #-} !Level -> Logger
- Z.IO.Logger: [flushLoggerThrottled] :: Logger -> IO ()
- Z.IO.Logger: [flushLogger] :: Logger -> IO ()
- Z.IO.Logger: [loggerFmt] :: Logger -> LogFormatter
- Z.IO.Logger: [loggerLevel] :: Logger -> {-# UNPACK #-} !Level
- Z.IO.Logger: [loggerPushBuilder] :: Logger -> Builder () -> IO ()
- Z.IO.Logger: [loggerTSCache] :: Logger -> IO (Builder ())
- Z.IO.Logger: defaultTSCache :: IO (Builder ())
- Z.IO.Logger: flushLogIORef :: HasCallStack => MVar BufferedOutput -> IORef [Bytes] -> IO ()
- Z.IO.Logger: newColoredLogger :: LoggerConfig -> IO Logger
- Z.IO.Logger: newJSONLogger :: LoggerConfig -> MVar BufferedOutput -> IO Logger
- Z.IO.Logger: pushLogIORef :: IORef [Bytes] -> Int -> Builder () -> IO ()
- Z.IO.UV.Win: withUVInitDo :: IO a -> IO a
+ Z.IO.FileSystem.Watch: initWatchDirs :: [CBytes] -> Bool -> Resource (IO (Source FileEvent))
+ Z.IO.Logger: [loggerFormatter] :: LoggerConfig -> LogFormatter
+ Z.IO.Logger: defaultJSONLoggerConfig :: LoggerConfig
+ Z.IO.Logger: newFileLogger :: LoggerConfig -> CBytes -> IO Logger
+ Z.IO.Logger: newStdLogger :: LoggerConfig -> IO Logger
- Z.IO.FileSystem.Watch: watchDirs :: [CBytes] -> IO (IO (), IO (Source FileEvent))
+ Z.IO.FileSystem.Watch: watchDirs :: [CBytes] -> Bool -> (FileEvent -> IO ()) -> IO ()
- Z.IO.Logger: LoggerConfig :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Level -> LoggerConfig
+ Z.IO.Logger: LoggerConfig :: {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Level -> LogFormatter -> LoggerConfig
- Z.IO.Logger: type LogFormatter = Builder () " data\/time string" -> Level " log level" -> Builder () " log content" -> CallStack " call stack trace" -> ThreadId " logging thread id" -> Builder ()
+ Z.IO.Logger: type LogFormatter = Builder () " data\/time string(second precision)" -> Level " log level" -> Builder () " log content" -> CallStack " call stack trace" -> ThreadId " logging thread id" -> Builder ()
- Z.IO.Resource: initResource_ :: IO () -> IO () -> Resource ()
+ Z.IO.Resource: initResource_ :: IO a -> IO () -> Resource a
Files
- ChangeLog.md +8/−0
- README.md +1/−1
- Z-IO.cabal +392/−360
- Z/IO/FileSystem/Base.hs +1/−1
- Z/IO/FileSystem/Watch.hs +40/−31
- Z/IO/Logger.hs +58/−41
- Z/IO/Network/UDP.hs +4/−4
- Z/IO/Resource.hs +1/−1
- Z/IO/StdStream.hs +38/−16
- Z/IO/UV/Manager.hs +1/−1
- bench/GetTime.hs +25/−0
- bench/Http.hs +46/−0
ChangeLog.md view
@@ -1,5 +1,13 @@ # Revision history for Z-IO +## 0.6.2.0 -- 2020-02-18++* Hide `Logger` constructor from `Z.IO.Logger`, remove implementation details such as `defaultTSCache`, `pushLogIORef`, `flushLogIORef`, add `loggerFormatter` to `LoggerConfig`.+* Add `newStdLogger/newFileLogger` to make new logger easily.+* Rework `Z.IO.FileSystem.Watch`'s API, change `watchDirs` to accept a recursive param and a callback.+* Hide `Z.IO.UV.Win` module, which should not be directly used by user.+* Fix a bug when stdio is redirected to pipes: https://github.com/ZHaskell/z-io/pull/16+ ## 0.6.1.0 -- 2020-02-09 * Fix a bug in `newMagicSplitter/newLineSplitter` code.
README.md view
@@ -32,7 +32,7 @@ > > -- call getAddrInfo to perform DNS > head <$> getAddrInfo Nothing "www.bing.com" "http"-AddrInfo {addrFlags = [AI_ADDRCONFIG,AI_V4MAPPED], addrFamily = SocketFamily 2, addrSocketType = SocketType 1, addrProtocol = ProtocolNumber 6, addrAddress = 204.79.197.200:80, addrCanonName = }+AddrInfo {addrFlags = [AI_ADDRCONFIG,AI_V4MAPPED], addrFamily = SocketFamily 2, addrSocketType = SocketType 1, addrProtocol = ProtocolNumber 6, addrAddress = 204.79.197.200:80, addrCanonName = ""} > > import qualified Z.Data.Text as T > -- send a simple HTTP request
Z-IO.cabal view
@@ -1,393 +1,425 @@-cabal-version: 2.4-name: Z-IO-version: 0.6.1.0-synopsis: Simple and high performance IO toolkit for Haskell-description: Simple and high performance IO toolkit for Haskell, including- file system, network, ipc and more!-license: BSD-3-Clause-license-file: LICENSE-author: Z.Haskell Contributors-maintainer: winterland1989@gmail.com-copyright: (c) Z.Haskell Contributors-category: Data-build-type: Simple-homepage: https://github.com/ZHaskell/Z-IO-bug-reports: https://github.com/ZHaskell/Z-IO/issues--extra-source-files: ChangeLog.md- README.md- LICENSE-- -- shared Haskell soruce- Z/IO/FileSystem/_Shared.hs-- -- zlib C sources- third_party/zlib/crc32.h- third_party/zlib/inffast.h - third_party/zlib/inflate.h- third_party/zlib/trees.h - third_party/zlib/deflate.h - third_party/zlib/inffixed.h- third_party/zlib/inftrees.h - third_party/zlib/zutil.h- third_party/zlib/gzguts.h-- -- cwalk header- third_party/cwalk/include/cwalk.h-- -- libuv C sources- third_party/libuv/include/uv.h- third_party/libuv/include/uv/aix.h- third_party/libuv/include/uv/android-ifaddrs.h- third_party/libuv/include/uv/bsd.h- third_party/libuv/include/uv/darwin.h- third_party/libuv/include/uv/errno.h- third_party/libuv/include/uv/linux.h- third_party/libuv/include/uv/os390.h- third_party/libuv/include/uv/posix.h- third_party/libuv/include/uv/stdint-msvc2008.h- third_party/libuv/include/uv/sunos.h- third_party/libuv/include/uv/threadpool.h- third_party/libuv/include/uv/tree.h- third_party/libuv/include/uv/unix.h- third_party/libuv/include/uv/version.h- third_party/libuv/include/uv/win.h-- third_party/libuv/src/heap-inl.h- third_party/libuv/src/idna.h- third_party/libuv/src/queue.h- third_party/libuv/src/strscpy.h- third_party/libuv/src/uv-common.h-- third_party/libuv/src/win/atomicops-inl.h- third_party/libuv/src/win/fs-fd-hash-inl.h- third_party/libuv/src/win/handle-inl.h- third_party/libuv/src/win/internal.h- third_party/libuv/src/win/req-inl.h- third_party/libuv/src/win/stream-inl.h- third_party/libuv/src/win/winapi.h- third_party/libuv/src/win/winsock.h+cabal-version: 2.4+name: Z-IO+version: 0.6.2.0+synopsis: Simple and high performance IO toolkit for Haskell+description:+ Simple and high performance IO toolkit for Haskell, including+ file system, network, ipc and more! - third_party/libuv/src/unix/atomic-ops.h- third_party/libuv/src/unix/darwin-stub.h- third_party/libuv/src/unix/darwin-stub.h- third_party/libuv/src/unix/internal.h- third_party/libuv/src/unix/linux-syscalls.h- third_party/libuv/src/unix/spinlock.h- third_party/libuv/src/unix/os390-syscalls.h+license: BSD-3-Clause+license-file: LICENSE+author: Z.Haskell Contributors+maintainer: winterland1989@gmail.com+copyright: (c) Z.Haskell Contributors+category: Data+build-type: Simple+homepage: https://github.com/ZHaskell/Z-IO+bug-reports: https://github.com/ZHaskell/Z-IO/issues+extra-source-files:+ ChangeLog.md+ LICENSE+ README.md+ third_party/cwalk/include/cwalk.h+ third_party/libuv/include/uv/aix.h+ third_party/libuv/include/uv/android-ifaddrs.h+ third_party/libuv/include/uv/bsd.h+ third_party/libuv/include/uv/darwin.h+ third_party/libuv/include/uv/errno.h+ third_party/libuv/include/uv/linux.h+ third_party/libuv/include/uv/os390.h+ third_party/libuv/include/uv/posix.h+ third_party/libuv/include/uv/stdint-msvc2008.h+ third_party/libuv/include/uv/sunos.h+ third_party/libuv/include/uv/threadpool.h+ third_party/libuv/include/uv/tree.h+ third_party/libuv/include/uv/unix.h+ third_party/libuv/include/uv/version.h+ third_party/libuv/include/uv/win.h+ third_party/libuv/include/uv.h+ third_party/libuv/src/heap-inl.h+ third_party/libuv/src/idna.h+ third_party/libuv/src/queue.h+ third_party/libuv/src/strscpy.h+ third_party/libuv/src/unix/atomic-ops.h+ third_party/libuv/src/unix/darwin-stub.h+ third_party/libuv/src/unix/internal.h+ third_party/libuv/src/unix/linux-syscalls.h+ third_party/libuv/src/unix/os390-syscalls.h+ third_party/libuv/src/unix/spinlock.h+ third_party/libuv/src/uv-common.h+ third_party/libuv/src/win/atomicops-inl.h+ third_party/libuv/src/win/fs-fd-hash-inl.h+ third_party/libuv/src/win/handle-inl.h+ third_party/libuv/src/win/internal.h+ third_party/libuv/src/win/req-inl.h+ third_party/libuv/src/win/stream-inl.h+ third_party/libuv/src/win/winapi.h+ third_party/libuv/src/win/winsock.h+ third_party/zlib/crc32.h+ third_party/zlib/deflate.h+ third_party/zlib/gzguts.h+ third_party/zlib/inffast.h+ third_party/zlib/inffixed.h+ third_party/zlib/inflate.h+ third_party/zlib/inftrees.h+ third_party/zlib/trees.h+ third_party/zlib/zutil.h+ Z/IO/FileSystem/_Shared.hs source-repository head- type: git- location: git://github.com/ZHaskell/Z-IO.git+ type: git+ location: git://github.com/ZHaskell/z-io.git -flag no-pkg-config- description: Don't use pkg-config to check for library dependences(on platforms other than linux, win and osx)- default: False- manual: True+flag demos+ description: Build benchamrk/demonstration programs+ default: False -library- exposed-modules: Z.IO- Z.IO.BIO- Z.IO.BIO.Zlib- Z.IO.BIO.Concurrent+flag no-pkg-config+ description:+ Don't use pkg-config to check for library dependences(on platforms other than linux, win and osx) - Z.IO.FileSystem- Z.IO.FileSystem.Base- Z.IO.FileSystem.Threaded- Z.IO.FileSystem.FilePath- Z.IO.FileSystem.Watch+ default: False+ manual: True - Z.IO.Network.SocketAddr- Z.IO.Network.DNS- Z.IO.Network.TCP- Z.IO.Network.UDP- Z.IO.Network.IPC- Z.IO.Network- Z.IO.Buffered- Z.IO.Exception- Z.IO.LowResTimer- Z.IO.Logger- Z.IO.Process- Z.IO.Resource- Z.IO.StdStream- Z.IO.StdStream.Ansi- Z.IO.Time+library+ exposed-modules:+ Z.IO+ Z.IO.BIO+ Z.IO.BIO.Concurrent+ Z.IO.BIO.Zlib+ Z.IO.Buffered+ Z.IO.Environment+ Z.IO.Exception+ Z.IO.FileSystem+ Z.IO.FileSystem.Base+ Z.IO.FileSystem.FilePath+ Z.IO.FileSystem.Threaded+ Z.IO.FileSystem.Watch+ Z.IO.Logger+ Z.IO.LowResTimer+ Z.IO.Network+ Z.IO.Network.DNS+ Z.IO.Network.IPC+ Z.IO.Network.SocketAddr+ Z.IO.Network.TCP+ Z.IO.Network.UDP+ Z.IO.Process+ Z.IO.Resource+ Z.IO.StdStream+ Z.IO.StdStream.Ansi+ Z.IO.Time+ Z.IO.UV.Errno+ Z.IO.UV.FFI+ Z.IO.UV.Manager+ Z.IO.UV.UVStream+ other-modules:+ Z.IO.UV.Win - Z.IO.UV.Errno- Z.IO.UV.FFI- Z.IO.UV.Manager- Z.IO.UV.UVStream- Z.IO.UV.Win+ build-depends:+ , base >=4.12 && <5.0+ , containers ^>=0.6+ , exceptions ^>=0.10+ , primitive >=0.7.1 && <0.7.2+ , stm ^>=2.5+ , time >=1.9 && <=2.0+ , unix-time >=0.4.7 && <=0.5+ , unordered-containers ^>=0.2+ , Z-Data ^>=0.6+ , microlens - Z.IO.Environment+ default-language: Haskell2010+ default-extensions:+ BangPatterns+ BinaryLiterals+ CApiFFI+ CPP+ ConstraintKinds+ DataKinds+ DefaultSignatures+ DeriveAnyClass+ DeriveGeneric+ DerivingStrategies+ ExistentialQuantification+ FlexibleContexts+ FlexibleInstances+ GeneralizedNewtypeDeriving+ KindSignatures+ MagicHash+ MultiParamTypeClasses+ MultiWayIf+ OverloadedStrings+ PartialTypeSignatures+ PatternSynonyms+ PolyKinds+ QuantifiedConstraints+ QuasiQuotes+ RankNTypes+ RecordWildCards+ ScopedTypeVariables+ StandaloneDeriving+ TemplateHaskell+ TupleSections+ TypeApplications+ TypeFamilies+ TypeFamilyDependencies+ TypeOperators+ UnboxedTuples+ UnliftedFFITypes+ ViewPatterns - -- Z.Compression.Zlib+ build-tool-depends: hsc2hs:hsc2hs -any, hspec-discover:hspec-discover -any+ ghc-options: -Wall+ include-dirs: include third_party/zlib third_party/cwalk/include+ includes:+ hs_cwalk.h+ hs_uv.h+ zconf.h+ zlib.h - build-depends: base >= 4.12 && <5.0- , exceptions == 0.10.*- , primitive >= 0.7.1 && < 0.7.2- , stm == 2.5.*- , unordered-containers == 0.2.*- , containers == 0.6.*- , Z-Data == 0.6.* - , time >= 1.9 && <= 2.0- , unix-time >= 0.4.7 && <= 0.5+ install-includes:+ hs_cwalk.h+ hs_uv.h+ zconf.h+ zlib.h - default-language: Haskell2010- default-extensions: BangPatterns- BinaryLiterals- CApiFFI- ConstraintKinds- CPP - DerivingStrategies- DeriveGeneric- DeriveAnyClass- DefaultSignatures- DataKinds- ExistentialQuantification- FlexibleContexts- FlexibleInstances- GeneralizedNewtypeDeriving - KindSignatures- MagicHash- MultiParamTypeClasses- MultiWayIf- PartialTypeSignatures- PatternSynonyms - PolyKinds- QuantifiedConstraints- QuasiQuotes- OverloadedStrings- RankNTypes- RecordWildCards- ScopedTypeVariables - StandaloneDeriving- TemplateHaskell- TypeApplications- TypeFamilyDependencies- TypeFamilies- TypeOperators- TupleSections- UnboxedTuples - UnliftedFFITypes - ViewPatterns- build-tool-depends: hsc2hs:hsc2hs, hspec-discover:hspec-discover- ghc-options: -Wall+ cc-options: -march=native -D_FILE_OFFSET_BITS=64+ c-sources:+ cbits/hs_cwalk.c+ cbits/hs_uv_base.c+ cbits/hs_uv_dns.c+ cbits/hs_uv_file.c+ cbits/hs_uv_fs_event.c+ cbits/hs_uv_process.c+ cbits/hs_uv_stream.c+ cbits/hs_uv_udp.c+ cbits/hs_zlib.c+ third_party/cwalk/src/cwalk.c+ third_party/libuv/src/fs-poll.c+ third_party/libuv/src/idna.c+ third_party/libuv/src/inet.c+ third_party/libuv/src/random.c+ third_party/libuv/src/strscpy.c+ third_party/libuv/src/threadpool.c+ third_party/libuv/src/timer.c+ third_party/libuv/src/uv-common.c+ third_party/libuv/src/uv-data-getter-setters.c+ third_party/libuv/src/version.c+ third_party/zlib/adler32.c+ third_party/zlib/compress.c+ third_party/zlib/crc32.c+ third_party/zlib/deflate.c+ third_party/zlib/infback.c+ third_party/zlib/inffast.c+ third_party/zlib/inflate.c+ third_party/zlib/inftrees.c+ third_party/zlib/trees.c+ third_party/zlib/uncompr.c+ third_party/zlib/zutil.c - include-dirs: include- third_party/zlib- third_party/cwalk/include+ -- Note: The c-sources list is taken from libuv's Makefile.mingw, needs to be+ -- updated when we bump up libuv's version.+ -- header files are ignored here, otherwise will confuse linker+ if os(windows)+ c-sources:+ third_party/libuv/src/win/async.c+ third_party/libuv/src/win/core.c+ third_party/libuv/src/win/detect-wakeup.c+ third_party/libuv/src/win/dl.c+ third_party/libuv/src/win/error.c+ third_party/libuv/src/win/fs-event.c+ third_party/libuv/src/win/fs.c+ third_party/libuv/src/win/getaddrinfo.c+ third_party/libuv/src/win/getnameinfo.c+ third_party/libuv/src/win/handle.c+ third_party/libuv/src/win/loop-watcher.c+ third_party/libuv/src/win/pipe.c+ third_party/libuv/src/win/poll.c+ third_party/libuv/src/win/process-stdio.c+ third_party/libuv/src/win/process.c+ third_party/libuv/src/win/signal.c+ third_party/libuv/src/win/stream.c+ third_party/libuv/src/win/tcp.c+ third_party/libuv/src/win/thread.c+ third_party/libuv/src/win/tty.c+ third_party/libuv/src/win/udp.c+ third_party/libuv/src/win/util.c+ third_party/libuv/src/win/winapi.c+ third_party/libuv/src/win/winsock.c - includes: hs_uv.h- zlib.h- zconf.h- hs_cwalk.h+ cc-options:+ -Wall -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600 -march=native - install-includes: hs_uv.h - zlib.h- zconf.h- hs_cwalk.h+ cpp-options: -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600+ include-dirs: third_party/libuv/include third_party/libuv/src - cc-options: -march=native -D_FILE_OFFSET_BITS=64- c-sources: cbits/hs_uv_base.c- cbits/hs_uv_dns.c- cbits/hs_uv_file.c- cbits/hs_uv_fs_event.c- cbits/hs_uv_stream.c- cbits/hs_uv_process.c- cbits/hs_uv_udp.c- cbits/hs_zlib.c- cbits/hs_cwalk.c+ -- The C runtime dependencies are imposed by libuv.+ extra-libraries:+ psapi+ Iphlpapi+ userenv+ Ws2_32 - third_party/cwalk/src/cwalk.c+ else+ if os(linux)+ c-sources:+ third_party/libuv/src/fs-poll.c+ third_party/libuv/src/idna.c+ third_party/libuv/src/inet.c+ third_party/libuv/src/random.c+ third_party/libuv/src/strscpy.c+ third_party/libuv/src/threadpool.c+ third_party/libuv/src/timer.c+ third_party/libuv/src/unix/async.c+ third_party/libuv/src/unix/core.c+ third_party/libuv/src/unix/dl.c+ third_party/libuv/src/unix/fs.c+ third_party/libuv/src/unix/getaddrinfo.c+ third_party/libuv/src/unix/getnameinfo.c+ third_party/libuv/src/unix/linux-core.c+ third_party/libuv/src/unix/linux-inotify.c+ third_party/libuv/src/unix/linux-syscalls.c+ third_party/libuv/src/unix/loop-watcher.c+ third_party/libuv/src/unix/loop.c+ third_party/libuv/src/unix/pipe.c+ third_party/libuv/src/unix/poll.c+ third_party/libuv/src/unix/process.c+ third_party/libuv/src/unix/procfs-exepath.c+ third_party/libuv/src/unix/proctitle.c+ third_party/libuv/src/unix/random-devurandom.c+ third_party/libuv/src/unix/random-getrandom.c+ third_party/libuv/src/unix/random-sysctl-linux.c+ third_party/libuv/src/unix/signal.c+ third_party/libuv/src/unix/stream.c+ third_party/libuv/src/unix/tcp.c+ third_party/libuv/src/unix/thread.c+ third_party/libuv/src/unix/tty.c+ third_party/libuv/src/unix/udp.c+ third_party/libuv/src/uv-common.c+ third_party/libuv/src/uv-data-getter-setters.c+ third_party/libuv/src/version.c - third_party/zlib/adler32.c- third_party/zlib/compress.c- third_party/zlib/crc32.c- third_party/zlib/deflate.c- third_party/zlib/infback.c- third_party/zlib/inffast.c- third_party/zlib/inflate.c- third_party/zlib/inftrees.c- third_party/zlib/trees.c- third_party/zlib/uncompr.c- third_party/zlib/zutil.c+ include-dirs:+ third_party/libuv/include third_party/libuv/src/unix+ third_party/libuv/src - third_party/libuv/src/fs-poll.c- third_party/libuv/src/idna.c- third_party/libuv/src/inet.c- third_party/libuv/src/random.c- third_party/libuv/src/strscpy.c- third_party/libuv/src/threadpool.c- third_party/libuv/src/timer.c- third_party/libuv/src/uv-data-getter-setters.c- third_party/libuv/src/uv-common.c- third_party/libuv/src/version.c+ cc-options: -Wall -march=native - -- Note: The c-sources list is taken from libuv's Makefile.mingw, needs to be- -- updated when we bump up libuv's version.- -- header files are ignored here, otherwise will confuse linker- if os(windows)+ else+ if os(osx) c-sources:- third_party/libuv/src/win/async.c- third_party/libuv/src/win/core.c- third_party/libuv/src/win/detect-wakeup.c- third_party/libuv/src/win/dl.c- third_party/libuv/src/win/error.c- third_party/libuv/src/win/fs-event.c- third_party/libuv/src/win/fs.c- third_party/libuv/src/win/getaddrinfo.c- third_party/libuv/src/win/getnameinfo.c- third_party/libuv/src/win/handle.c- third_party/libuv/src/win/loop-watcher.c- third_party/libuv/src/win/pipe.c- third_party/libuv/src/win/poll.c- third_party/libuv/src/win/process-stdio.c- third_party/libuv/src/win/process.c- third_party/libuv/src/win/signal.c- third_party/libuv/src/win/stream.c- third_party/libuv/src/win/tcp.c- third_party/libuv/src/win/thread.c- third_party/libuv/src/win/tty.c- third_party/libuv/src/win/udp.c- third_party/libuv/src/win/util.c- third_party/libuv/src/win/winapi.c- third_party/libuv/src/win/winsock.c+ third_party/libuv/src/fs-poll.c+ third_party/libuv/src/idna.c+ third_party/libuv/src/inet.c+ third_party/libuv/src/random.c+ third_party/libuv/src/strscpy.c+ third_party/libuv/src/threadpool.c+ third_party/libuv/src/timer.c+ third_party/libuv/src/unix/async.c+ third_party/libuv/src/unix/bsd-ifaddrs.c+ third_party/libuv/src/unix/core.c+ third_party/libuv/src/unix/darwin-proctitle.c+ third_party/libuv/src/unix/darwin.c+ third_party/libuv/src/unix/dl.c+ third_party/libuv/src/unix/fs.c+ third_party/libuv/src/unix/fsevents.c+ third_party/libuv/src/unix/getaddrinfo.c+ third_party/libuv/src/unix/getnameinfo.c+ third_party/libuv/src/unix/kqueue.c+ third_party/libuv/src/unix/loop-watcher.c+ third_party/libuv/src/unix/loop.c+ third_party/libuv/src/unix/pipe.c+ third_party/libuv/src/unix/poll.c+ third_party/libuv/src/unix/process.c+ third_party/libuv/src/unix/proctitle.c+ third_party/libuv/src/unix/random-devurandom.c+ third_party/libuv/src/unix/random-getentropy.c+ third_party/libuv/src/unix/signal.c+ third_party/libuv/src/unix/stream.c+ third_party/libuv/src/unix/tcp.c+ third_party/libuv/src/unix/thread.c+ third_party/libuv/src/unix/tty.c+ third_party/libuv/src/unix/udp.c+ third_party/libuv/src/uv-common.c+ third_party/libuv/src/uv-data-getter-setters.c+ third_party/libuv/src/version.c - cc-options: -Wall -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600 -march=native- cpp-options: -DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0600- include-dirs: third_party/libuv/include- third_party/libuv/src- -- The C runtime dependencies are imposed by libuv.- extra-libraries: psapi, Iphlpapi, userenv, Ws2_32- else- if os(linux)- c-sources: third_party/libuv/src/fs-poll.c- third_party/libuv/src/idna.c- third_party/libuv/src/inet.c- third_party/libuv/src/random.c- third_party/libuv/src/strscpy.c- third_party/libuv/src/threadpool.c- third_party/libuv/src/timer.c- third_party/libuv/src/uv-data-getter-setters.c- third_party/libuv/src/uv-common.c- third_party/libuv/src/version.c+ include-dirs:+ third_party/libuv/include third_party/libuv/src/unix+ third_party/libuv/src - third_party/libuv/src/unix/async.c- third_party/libuv/src/unix/core.c- third_party/libuv/src/unix/dl.c- third_party/libuv/src/unix/fs.c- third_party/libuv/src/unix/getaddrinfo.c- third_party/libuv/src/unix/getnameinfo.c- third_party/libuv/src/unix/loop.c- third_party/libuv/src/unix/loop-watcher.c- third_party/libuv/src/unix/pipe.c- third_party/libuv/src/unix/poll.c- third_party/libuv/src/unix/process.c- third_party/libuv/src/unix/random-devurandom.c- third_party/libuv/src/unix/signal.c- third_party/libuv/src/unix/stream.c- third_party/libuv/src/unix/tcp.c- third_party/libuv/src/unix/thread.c- third_party/libuv/src/unix/tty.c- third_party/libuv/src/unix/udp.c+ cc-options: -Wall -march=native - third_party/libuv/src/unix/linux-core.c- third_party/libuv/src/unix/linux-inotify.c- third_party/libuv/src/unix/linux-syscalls.c- third_party/libuv/src/unix/procfs-exepath.c- third_party/libuv/src/unix/proctitle.c- third_party/libuv/src/unix/random-getrandom.c- third_party/libuv/src/unix/random-sysctl-linux.c+ else+ if flag(no-pkg-config)+ extra-libraries: uv - include-dirs: third_party/libuv/include- third_party/libuv/src/unix- third_party/libuv/src- cc-options: -Wall -march=native else- if os(osx)- c-sources: third_party/libuv/src/fs-poll.c- third_party/libuv/src/idna.c- third_party/libuv/src/inet.c- third_party/libuv/src/random.c- third_party/libuv/src/strscpy.c- third_party/libuv/src/threadpool.c- third_party/libuv/src/timer.c- third_party/libuv/src/uv-data-getter-setters.c- third_party/libuv/src/uv-common.c- third_party/libuv/src/version.c+ pkgconfig-depends: libuv ==1.32 || >1.32 - third_party/libuv/src/unix/async.c- third_party/libuv/src/unix/core.c- third_party/libuv/src/unix/dl.c- third_party/libuv/src/unix/fs.c- third_party/libuv/src/unix/getaddrinfo.c- third_party/libuv/src/unix/getnameinfo.c- third_party/libuv/src/unix/loop.c- third_party/libuv/src/unix/loop-watcher.c- third_party/libuv/src/unix/pipe.c- third_party/libuv/src/unix/poll.c- third_party/libuv/src/unix/process.c- third_party/libuv/src/unix/random-devurandom.c- third_party/libuv/src/unix/signal.c- third_party/libuv/src/unix/stream.c- third_party/libuv/src/unix/tcp.c- third_party/libuv/src/unix/thread.c- third_party/libuv/src/unix/tty.c- third_party/libuv/src/unix/udp.c+test-suite Z-IO-Test+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test/+ build-depends:+ , base+ , bytestring+ , hashable+ , hspec >=2.5.4+ , HUnit+ , primitive+ , QuickCheck >=2.10+ , quickcheck-instances+ , scientific+ , Z-Data+ , Z-IO+ , zlib - third_party/libuv/src/unix/bsd-ifaddrs.c- third_party/libuv/src/unix/darwin-proctitle.c- third_party/libuv/src/unix/darwin.c- third_party/libuv/src/unix/fsevents.c- third_party/libuv/src/unix/kqueue.c- third_party/libuv/src/unix/proctitle.c- third_party/libuv/src/unix/random-getentropy.c- - include-dirs: third_party/libuv/include- third_party/libuv/src/unix- third_party/libuv/src- cc-options: -Wall -march=native+ other-modules:+ Z.IO.BIO.ConcurrentSpec+ Z.IO.BIO.ZlibSpec+ Z.IO.BIOSpec+ Z.IO.FileSystem.ThreadedSpec+ Z.IO.FileSystemSpec+ Z.IO.LowResTimerSpec+ Z.IO.Network.IPCSpec+ Z.IO.Network.TCPSpec+ Z.IO.Network.UDPSpec+ Z.IO.ProcessSpec+ Z.IO.ResourceSpec - else- if flag(no-pkg-config)- extra-libraries: uv- else- pkgconfig-depends: libuv >= 1.32- -test-suite Z-IO-Test- type: exitcode-stdio-1.0- main-is: Spec.hs- hs-source-dirs: test/- build-depends: base- , Z-IO - , Z-Data- , hspec >= 2.5.4- , hashable- , HUnit- , QuickCheck >= 2.10- , quickcheck-instances- , scientific- , primitive- , zlib- , bytestring+ if os(linux)+ other-modules: Z.IO.Network.IPCSpec - other-modules: Z.IO.BIOSpec- Z.IO.BIO.ZlibSpec- Z.IO.BIO.ConcurrentSpec- Z.IO.FileSystem.ThreadedSpec- Z.IO.FileSystemSpec- Z.IO.Network.UDPSpec- Z.IO.Network.TCPSpec- Z.IO.Network.IPCSpec- Z.IO.LowResTimerSpec- Z.IO.ProcessSpec- Z.IO.ResourceSpec+ ghc-options: -threaded+ default-language: Haskell2010+ build-tool-depends: hspec-discover:hspec-discover ==2.* +benchmark z-io-gettime+ type: exitcode-stdio-1.0+ main-is: GetTime.hs+ hs-source-dirs: bench/+ build-depends:+ , base+ , criterion ^>=1.5+ , time ^>=1.9+ , Z-Data+ , Z-IO - if os(linux)- other-modules: Z.IO.Network.IPCSpec+ default-language: Haskell2010 - ghc-options: -threaded- default-language: Haskell2010- build-tool-depends: hspec-discover:hspec-discover == 2.*+ if !flag(demos)+ buildable: False++executable z-io-http-bench+ main-is: Http.hs+ hs-source-dirs: bench/+ build-depends:+ , base+ , Z-Data+ , Z-IO++ default-language: Haskell2010+ ghc-options: -threaded -rtsopts -with-rtsopts=-N++ if !flag(demos)+ buildable: False
Z/IO/FileSystem/Base.hs view
@@ -233,7 +233,7 @@ initFile :: HasCallStack => CBytes -> FileFlag -- ^ Opening flags, e.g. 'O_CREAT' @.|.@ 'O_RDWR'- -> FileMode -- ^ Sets the file mode (permission and sticky bits),+ -> FileMode -- ^ Sets the file mode (permission and sticky bits), -- but only if the file was created, see 'DEFAULT_FILE_MODE'. -> Resource File initFile path flags mode =
Z/IO/FileSystem/Watch.hs view
@@ -11,30 +11,30 @@ support recursive watch(Linux's inotify). @--- start watching threads, use returned close function to cleanup watching threads.-(close, srcf) <- watchDirs ["fold_to_be_watch"]--- dup a file event source-src <- srcf--- print event to stdout-runBIO $ src >|> sinkToIO printLineStd+-- start watching threads, cleanup watching threads automatically when finished.+withResource (initWatchDirs ["fold_to_be_watch"] True) $ \ srcf -> do+ -- dup a file event source+ src <- srcf+ -- print event to stdout+ runBIO $ src >|> sinkToIO printStd @ -} -module Z.IO.FileSystem.Watch (- FileEvent(..)- , watchDirs- , watchDirsRecursively- ) where+module Z.IO.FileSystem.Watch+ ( FileEvent(..)+ , watchDirs+ , initWatchDirs+ ) where import Control.Concurrent import Control.Monad import Data.Bits-import Data.IORef import qualified Data.HashMap.Strict as HM+import Data.IORef import qualified Data.List as List+import Data.Primitive.PrimArray import Data.Word import GHC.Generics-import Data.Primitive.PrimArray import Z.Data.Array import Z.Data.Array.Unaligned import Z.Data.CBytes (CBytes)@@ -48,40 +48,48 @@ import Z.IO.Exception import Z.IO.FileSystem.Base import qualified Z.IO.FileSystem.FilePath as P+import Z.IO.LowResTimer+import Z.IO.Resource import Z.IO.UV.FFI import Z.IO.UV.Manager-import Z.IO.LowResTimer -- | File event with path info. data FileEvent = FileAdd CBytes | FileRemove CBytes | FileModify CBytes- deriving (Show, Read, Ord, Eq, Generic)- deriving anyclass (Print, JSON)+ deriving (Show, Read, Ord, Eq, Generic)+ deriving anyclass (Print, JSON) +-- | Watching a list of given directories.+watchDirs :: [CBytes] -- ^ Directories to be watched+ -> Bool -- ^ recursively watch?+ -> (FileEvent -> IO ()) -- ^ Callback function to handle 'FileEvent'+ -> IO ()+watchDirs dirs rec callback = do+ withResource (initWatchDirs dirs rec) $ \ srcf -> do+ src <- srcf+ runBIO $ src >|> sinkToIO callback --- | Start watching a list of given directories.----watchDirs :: [CBytes] -> IO (IO (), IO (Source FileEvent))-watchDirs dirs = do- forM_ dirs $ \ dir -> do+-- | Start watching a list of given directories, stream version.+initWatchDirs :: [CBytes] -- ^ watching list+ -> Bool -- ^ recursively watch?+ -> Resource (IO (Source FileEvent))+initWatchDirs dirs False = do+ liftIO . forM_ dirs $ \ dir -> do b <- isDir dir unless b (throwUVIfMinus_ (return UV_ENOTDIR)) watch_ 0 dirs---- | Start watching a list of given directories recursively.----watchDirsRecursively :: [CBytes] -> IO (IO (), IO (Source FileEvent))-watchDirsRecursively dirs = do+initWatchDirs dirs _ = do #if defined(linux_HOST_OS) -- inotify doesn't support recursive watch, so we manually maintain watch list- subDirs <- forM dirs (\ dir -> scandirRecursively dir (\ _ t -> return (t == DirEntDir)))+ subDirs <- liftIO . forM dirs $ \ dir ->+ scandirRecursively dir (\ _ t -> return (t == DirEntDir)) watch_ UV_FS_EVENT_RECURSIVE (List.concat (dirs:subDirs)) #else watch_ UV_FS_EVENT_RECURSIVE dirs #endif -- Internal function to start watching-watch_ :: CUInt -> [CBytes] -> IO (IO (), IO (Source FileEvent))-watch_ flag dirs = do+watch_ :: CUInt -> [CBytes] -> Resource (IO (Source FileEvent))+watch_ flag dirs = fst <$> initResource (do -- HashMap to store all watchers mRef <- newMVar HM.empty -- there's only one place to pull the sink, that is cleanUpWatcher@@ -92,7 +100,8 @@ tid <- forkIO $ watchThread mRef dir' sink modifyMVar_ mRef $ \ m -> return $! HM.insert dir' tid m) `onException` cleanUpWatcher mRef sink- return (cleanUpWatcher mRef sink, srcf)+ return (srcf, (sink, mRef)))+ (\ (_, (sink, mRef)) -> cleanUpWatcher mRef sink) where eventBufSiz = defaultChunkSize @@ -195,7 +204,7 @@ me' <- atomicModifyIORef' eRef $ \ me -> case me of Just e -> (Nothing, Just e)- _ -> (Nothing, Nothing)+ _ -> (Nothing, Nothing) forM_ me' (push sink) me' <- atomicModifyIORef' eRef $ \ me ->
Z/IO/Logger.hs view
@@ -37,16 +37,20 @@ module Z.IO.Logger ( -- * A simple Logger type- Logger(..)+ Logger , LoggerConfig(..) , defaultLoggerConfig+ , defaultJSONLoggerConfig , setDefaultLogger , getDefaultLogger , flushDefaultLogger , withDefaultLogger++ -- * Create a new logger , newLogger- , newColoredLogger- , newJSONLogger+ , newStdLogger+ , newFileLogger+ -- * logging functions , debug , info@@ -54,18 +58,19 @@ , fatal , critical , otherLevel+ -- * logging functions with specific logger , debugTo , infoTo , warningTo , fatalTo , otherLevelTo- -- * Helpers to write new logger- , defaultTSCache++ -- * Helpers to write new log formatter+ , LogFormatter, defaultFmt, defaultColoredFmt, defaultJSONFmt , defaultFmtCallStack , defaultLevelFmt- , LogFormatter, defaultFmt, defaultColoredFmt, defaultJSONFmt- , pushLogIORef, flushLogIORef+ -- * Constants -- ** Level , Level@@ -79,24 +84,29 @@ import Control.Concurrent.MVar import Control.Monad+import Data.Bits ((.|.)) import Data.IORef-import Foreign.C.Types (CInt(..))-import GHC.Conc.Sync (ThreadId(..), myThreadId)+import Foreign.C.Types (CInt (..))+import GHC.Conc.Sync (ThreadId (..), myThreadId) import GHC.Exts (ThreadId#) import GHC.Stack import System.IO.Unsafe (unsafePerformIO) import qualified Z.Data.Builder as B-import qualified Z.Data.JSON.Builder as JB import qualified Z.Data.CBytes as CB+import qualified Z.Data.JSON.Builder as JB import Z.Data.Vector.Base as V import Z.IO.Buffered import Z.IO.Exception+import qualified Z.IO.FileSystem as ZF import Z.IO.LowResTimer+import Z.IO.Resource import Z.IO.StdStream import Z.IO.StdStream.Ansi (AnsiColor (..), color) import Z.IO.Time -type LogFormatter = B.Builder () -- ^ data\/time string+-------------------------------------------------------------------------------++type LogFormatter = B.Builder () -- ^ data\/time string(second precision) -> Level -- ^ log level -> B.Builder () -- ^ log content -> CallStack -- ^ call stack trace@@ -127,6 +137,8 @@ -- ^ Buffer size to build each log line , loggerConfigLevel :: {-# UNPACK #-} !Level -- ^ Config log's filter level+ , loggerFormatter :: LogFormatter+ -- ^ Log formatter } -- | A default logger config with@@ -134,9 +146,19 @@ -- * 0.1s minimal flush interval -- * line buffer size 240 bytes -- * show everything by default+-- * 'defaultFmt' defaultLoggerConfig :: LoggerConfig-defaultLoggerConfig = LoggerConfig 1 240 NOTSET+defaultLoggerConfig = LoggerConfig 1 240 NOTSET defaultFmt +-- | A default logger config with+--+-- * 0.5s minimal flush interval+-- * line buffer size 1000 bytes+-- * show everything by default+-- * 'defaultJSONFmt'+defaultJSONLoggerConfig :: LoggerConfig+defaultJSONLoggerConfig = LoggerConfig 5 1000 NOTSET defaultJSONFmt+ -- | A default timestamp cache with format @%Y-%m-%dT%H:%M:%S%Z@('iso8061DateFormat'). -- -- The timestamp will updated in 0.1s granularity to ensure a seconds level precision.@@ -147,22 +169,9 @@ t <- getSystemTime' CB.toBuilder <$> formatSystemTime iso8061DateFormat t --- | Make a new colored logger(connected to stderr).------ This logger will output colorized log if stderr is connected to TTY.-newColoredLogger :: LoggerConfig -> IO Logger-newColoredLogger LoggerConfig{..} = do- logsRef <- newIORef []- let flush = flushLogIORef stderrBuf logsRef- throttledFlush <- throttleTrailing_ loggerMinFlushInterval flush- return $ Logger (pushLogIORef logsRef loggerLineBufSize)- flush throttledFlush defaultTSCache- (if isStdStreamTTY stderr then defaultColoredFmt- else defaultFmt)- loggerConfigLevel+------------------------------------------------------------------------------- --- | Make a new simple logger, see 'defaultFmt'.---+-- | Make a new logger with given write device. newLogger :: LoggerConfig -> MVar BufferedOutput -> IO Logger@@ -171,22 +180,25 @@ let flush = flushLogIORef oLock logsRef throttledFlush <- throttleTrailing_ loggerMinFlushInterval flush return $ Logger (pushLogIORef logsRef loggerLineBufSize)- flush throttledFlush defaultTSCache defaultFmt+ flush throttledFlush defaultTSCache loggerFormatter loggerConfigLevel --- | Make a new structured JSON logger, see 'defaultJSONFmt'+-- | Make a new logger write to 'stderrBuf'.+newStdLogger :: LoggerConfig -> IO Logger+newStdLogger config = newLogger config stderrBuf++-- | Make a new file based logger with 'defaultFmt'. ---newJSONLogger :: LoggerConfig- -> MVar BufferedOutput- -> IO Logger-newJSONLogger LoggerConfig{..} oLock = do- logsRef <- newIORef []- let flush = flushLogIORef oLock logsRef- throttledFlush <- throttleTrailing_ loggerMinFlushInterval flush- return $ Logger (pushLogIORef logsRef loggerLineBufSize)- flush throttledFlush defaultTSCache defaultJSONFmt- loggerConfigLevel+-- The file will be opened in append mode.+newFileLogger :: LoggerConfig -> CB.CBytes -> IO Logger+newFileLogger config path = do+ let res = ZF.initFile path (ZF.O_CREAT .|. ZF.O_RDWR .|. ZF.O_APPEND) ZF.DEFAULT_FILE_MODE+ (file, _closeFunc) <- acquire res+ oLock <- newMVar =<< newBufferedOutput file+ newLogger config oLock +-------------------------------------------------------------------------------+ -- | Use 'pushLogIORef' and 'pushLogIORef' to implement a simple 'IORef' based concurrent logger. -- -- @@@ -245,7 +257,7 @@ -- | A default JSON log formatter. ----- @{"level":"FATAL","time":"2021-02-01T15:02:19+0800","loc":"<interactive>:27:1","theadId":606,"content":"..."}\\n@+-- > {"level":"FATAL","time":"2021-02-01T15:02:19+0800","loc":"<interactive>:27:1","theadId":606,"content":"..."}\n defaultJSONFmt :: LogFormatter defaultJSONFmt ts level content cstack (ThreadId tid#) = do B.curly $ do@@ -275,13 +287,18 @@ globalLogger :: IORef Logger {-# NOINLINE globalLogger #-} globalLogger = unsafePerformIO $- newIORef =<< newColoredLogger defaultLoggerConfig+ newIORef =<< newStdLogger defaultLoggerConfig{+ loggerFormatter = (if isStdStreamTTY stderr then defaultColoredFmt else defaultFmt)+ } -- | Change the global logger. setDefaultLogger :: Logger -> IO () setDefaultLogger !logger = atomicWriteIORef globalLogger logger -- | Get the global logger.+--+-- This is a logger connected to stderr, if stderr is connect to TTY,+-- then use 'defaultColoredFmt', otherwise use 'defaultFmt'. getDefaultLogger :: IO Logger getDefaultLogger = readIORef globalLogger
Z/IO/Network/UDP.hs view
@@ -88,10 +88,10 @@ -- Use 'MVar' 'UDP' in multiple threads. -- data UDP = UDP- { udpHandle :: {-# UNPACK #-} !(Ptr UVHandle)- , udpSlot :: {-# UNPACK #-} !UVSlot- , udpManager :: UVManager- , udpSendBuffer :: {-# UNPACK #-} !(A.MutablePrimArray RealWorld Word8)+ { _udpHandle :: {-# UNPACK #-} !(Ptr UVHandle)+ , _udpSlot :: {-# UNPACK #-} !UVSlot+ , _udpManager :: UVManager+ , _udpSendBuffer :: {-# UNPACK #-} !(A.MutablePrimArray RealWorld Word8) , udpClosed :: {-# UNPACK #-} !(IORef Bool) }
Z/IO/Resource.hs view
@@ -85,7 +85,7 @@ -- This function is useful when you want to add some initialization and clean up action -- inside 'Resource' monad. ---initResource_ :: IO () -> IO () -> Resource ()+initResource_ :: IO a -> IO () -> Resource a {-# INLINE initResource_ #-} initResource_ create release = Resource $ do r <- create
Z/IO/StdStream.hs view
@@ -79,14 +79,18 @@ -- For the same reason you shouldn't use stderr directly, use `Z.IO.Logger` module instead. data StdStream- = StdTTY {-# UNPACK #-}!(Ptr UVHandle) {-# UNPACK #-}!UVSlot UVManager -- similar to UVStream- | StdFile {-# UNPACK #-}!FD -- similar to UVFile+ = StdStream Bool {-# UNPACK #-}!(Ptr UVHandle) {-# UNPACK #-}!UVSlot UVManager+ -- ^ similar to UVStream, first field is is_tty+ | StdFile {-# UNPACK #-}!FD+ -- ^ similar to UVFile instance Show StdStream where show = T.toString instance T.Print StdStream where- toUTF8BuilderP p (StdTTY ptr slot uvm) = T.parenWhen (p > 10) $ do- "StdTTY "+ toUTF8BuilderP p (StdStream istty ptr slot uvm) = T.parenWhen (p > 10) $ do+ if istty+ then "StdStream(TTY) "+ else "StdStream " T.toUTF8Builder ptr T.char7 ' ' T.toUTF8Builder slot@@ -97,16 +101,16 @@ T.toUTF8Builder fd isStdStreamTTY :: StdStream -> Bool-isStdStreamTTY (StdTTY _ _ _) = True-isStdStreamTTY _ = False+isStdStreamTTY (StdStream istty _ _ _) = istty+isStdStreamTTY _ = False getStdStreamFD :: StdStream -> IO FD-getStdStreamFD (StdTTY hdl _ _) = throwUVIfMinus (hs_uv_fileno hdl)+getStdStreamFD (StdStream _ hdl _ _) = throwUVIfMinus (hs_uv_fileno hdl) getStdStreamFD (StdFile fd) = return fd instance Input StdStream where {-# INLINE readInput #-}- readInput (StdTTY hdl slot uvm) buf len = mask_ $ do+ readInput (StdStream _ hdl slot uvm) buf len = mask_ $ do pokeBufferTable uvm slot buf len m <- getBlockMVar uvm slot _ <- tryTakeMVar m@@ -133,7 +137,7 @@ instance Output StdStream where {-# INLINE writeOutput #-}- writeOutput (StdTTY hdl _ uvm) buf len = mask_ $ do+ writeOutput (StdStream _ hdl _ uvm) buf len = mask_ $ do m <- withUVManager' uvm $ do reqSlot <- getUVSlot uvm (hs_uv_write hdl buf len) m <- getBlockMVar uvm reqSlot@@ -195,21 +199,39 @@ makeStdStream :: HasCallStack => FD -> IO StdStream makeStdStream fd = do typ <- uv_guess_handle fd- if typ == UV_TTY- then mask_ $ do+ if typ == UV_FILE+ then return (StdFile fd)+ else mask_ $ do uvm <- getUVManager withUVManager uvm $ \ loop -> do hdl <- hs_uv_handle_alloc loop slot <- getUVSlot uvm (peekUVHandleData hdl) _ <- tryTakeMVar =<< getBlockMVar uvm slot -- clear the parking spot- throwUVIfMinus_ (uv_tty_init loop hdl (fromIntegral fd))- return (StdTTY hdl slot uvm)- else return (StdFile fd)+ case typ of+ UV_TTY -> do+ throwUVIfMinus_ (uv_tty_init loop hdl (fromIntegral fd))+ return (StdStream True hdl slot uvm)+ UV_TCP -> do+ throwUVIfMinus_ (uv_tcp_init loop hdl)+ throwUVIfMinus_ (uv_tcp_open hdl fd)+ return (StdStream False hdl slot uvm)+ UV_UDP ->+ throwUVError UV_EXDEV IOEInfo{+ ioeName = "EXDEV"+ , ioeDescription = "redirect to UDP is not supported"+ , ioeCallStack = callStack+ }+ -- normally this would be UV_NAMED_PIPE,+ -- but we also give UV_UNKNOWN_HANDLE a try.+ _ -> do+ throwUVIfMinus_ (uv_pipe_init loop hdl 0)+ throwUVIfMinus_ (uv_pipe_open hdl fd)+ return (StdStream False hdl slot uvm) -- | Change terminal's mode if stdin is connected to a terminal. setStdinTTYMode :: TTYMode -> IO () setStdinTTYMode mode = case stdin of- StdTTY hdl _ uvm ->+ StdStream _ hdl _ uvm -> withUVManager' uvm . throwUVIfMinus_ $ uv_tty_set_mode hdl mode _ -> return () @@ -217,7 +239,7 @@ -- return (-1, -1) if stdout is a file. getStdoutWinSize :: HasCallStack => IO (CInt, CInt) getStdoutWinSize = case stdout of- StdTTY hdl _ uvm ->+ StdStream _ hdl _ uvm -> withUVManager' uvm $ do (w, (h, ())) <- allocPrimUnsafe $ \ w -> allocPrimUnsafe $ \ h -> throwUVIfMinus_ $ uv_tty_get_winsize hdl w h
Z/IO/UV/Manager.hs view
@@ -65,7 +65,7 @@ data UVManager = UVManager { uvmBlockTable :: {-# UNPACK #-} !(IORef (UnliftedArray (MVar Int)))- -- ^ A array to store threads blocked on async IO.+ -- ^ An array to store threads blocked on async IO. , uvmLoop :: {-# UNPACK #-} !(Ptr UVLoop) -- ^ The uv loop refrerence , uvmLoopData :: {-# UNPACK #-} !(Ptr UVLoopData)
+ bench/GetTime.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeApplications #-}++{-| gettimeofday bench++This benchmark confirms an unneglectable overhead in common FFI bindings: the+overhead of doing pinned allocation.++Theoretically things will get worse under high concurrent load since pinned+allocation sometime requires lock GHC's sm.+-}+import Criterion.Main (Benchmark, bench, bgroup, defaultMain,+ nfIO)++import qualified Data.Time.Clock.System as T+import qualified Z.IO.Time as Z++main :: IO ()+main = do+ defaultMain+ [ bgroup "Z-IO"+ [ bench "gettimeofday-z" $ nfIO Z.getSystemTime'+ , bench "gettimeofday-time" $ nfIO T.getSystemTime+ ]+ ]
+ bench/Http.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++{-| HTTP benchmark test++This program read HTTP request(without parsing), and send some respond. You can+use HTTP benchmark tools such as ab or wrk to test IO throughput, remember to+add a proper heap size to improve performance (-Hx parammeter):++ulimit -n 10000+http-bench +RTS -H512M+wrk -c5000 http://localhost:8888++-}++module Main where++import Control.Monad+import Foreign.ForeignPtr+import qualified Z.Data.Vector as V+import qualified Z.Foreign as FFI+import Z.IO+import Z.IO.Network++main :: IO ()+main = startTCPServer defaultTCPServerConfig $ \ uvs -> do+ recvbuf <- mallocForeignPtrBytes 2048+ sendcontent' <- FFI.pinPrimVector sendcontent+ catch (echo uvs recvbuf sendcontent') (\ (e::SomeException) -> return ())+ where+ echo uvs recvbuf sendcontent' = loop+ where+ loop = do+ r <- withForeignPtr recvbuf $ \ p -> do+ readInput uvs p 2048+ when (r /= 0) $ do+ FFI.withPrimVectorSafe sendcontent' $ writeOutput uvs+ loop++ sendcontent :: V.Bytes+ sendcontent =+ "HTTP/1.1 200 OK\r\n\+ \Content-Type: text/html; charset=UTF-8\r\n\+ \Content-Length: 500\r\n\+ \Connection: Keep-Alive\r\n\+ \\r\n" `V.append` (V.pack $ replicate 500 48)