on master help sign in
Only use atomic-primops on GHC 7.8
a7a78e6Michael Snoyman
warp/Network/Wai/Handler/Warp/Counter.hs+21
@@ -1,3 +1,4 @@
1+{-# LANGUAGE CPP #-}
1module Network.Wai.Handler.Warp.Counter (
2module Network.Wai.Handler.Warp.Counter (
2 Counter
3 Counter
3 , newCounter
4 , newCounter
@@ -6,6 +7,7 @@ module Network.Wai.Handler.Warp.Counter (
6 , decrease
7 , decrease
7 ) where
8 ) where
8
9
10+#if USE_ATOMIC_PRIMOPS
9import qualified Data.Atomics.Counter.Unboxed as C
11import qualified Data.Atomics.Counter.Unboxed as C
10import Control.Applicative ((<$>))
12import Control.Applicative ((<$>))
11
13
@@ -22,3 +24,22 @@ increase (Counter ref) = C.incrCounter_ 1 ref
22
24
23decrease :: Counter -> IO ()
25decrease :: Counter -> IO ()
24decrease (Counter ref) = C.incrCounter_ (-1) ref
26decrease (Counter ref) = C.incrCounter_ (-1) ref
27+#else
28+
29+import Network.Wai.Handler.Warp.IORef
30+import Control.Applicative ((<$>))
31+
32+newtype Counter = Counter (IORef Int)
33+
34+newCounter :: IO Counter
35+newCounter = Counter <$> newIORef 0
36+
37+isZero :: Counter -> IO Bool
38+isZero (Counter ref) = (== 0) <$> readIORef ref
39+
40+increase :: Counter -> IO ()
41+increase (Counter ref) = atomicModifyIORef' ref (\x -> (x + 1, ()))
42+
43+decrease :: Counter -> IO ()
44+decrease (Counter ref) = atomicModifyIORef' ref (\x -> (x - 1, ()))
45+#endif
warp/Network/Wai/Handler/Warp/Timeout.hs+35−5
@@ -59,7 +59,12 @@ import GHC.Weak (Weak (..))
59import System.Mem.Weak (deRefWeak)
59import System.Mem.Weak (deRefWeak)
60import Data.Typeable (Typeable)
60import Data.Typeable (Typeable)
61import Control.Reaper
61import Control.Reaper
62+#if USE_ATOMIC_PRIMOPS
62import qualified Data.Atomics.Counter.Unboxed as C
63import qualified Data.Atomics.Counter.Unboxed as C
64+import Data.Atomics.Counter.Unboxed (casCounter)
65+#else
66+import Network.Wai.Handler.Warp.IORef
67+#endif
63
68
64----------------------------------------------------------------
69----------------------------------------------------------------
65
70
@@ -70,7 +75,12 @@ type Manager = Reaper [Handle] Handle
70type TimeoutAction = IO ()
75type TimeoutAction = IO ()
71
76
72-- | A handle used by 'Manager'
77-- | A handle used by 'Manager'
73−data Handle = Handle TimeoutAction {-# UNPACK #-} !C.AtomicCounter
78+data Handle = Handle TimeoutAction
79+#if USE_ATOMIC_PRIMOPS
80+ {-# UNPACK #-} !C.AtomicCounter
81+#else
82+ {-# UNPACK #-} !(IORef Int)
83+#endif
74
84
75-- Four states for the AtomicCounter:
85-- Four states for the AtomicCounter:
76--
86--
@@ -91,7 +101,7 @@ initialize timeout = mkReaper defaultReaperSettings
91 where
101 where
92 prune m@(Handle onTimeout iactive) = do
102 prune m@(Handle onTimeout iactive) = do
93 -- Try to change from active to inactive
103 -- Try to change from active to inactive
94− (wasActive, newState) <- C.casCounter iactive 1 2
104+ (wasActive, newState) <- casCounter iactive 1 2
95 case newState of
105 case newState of
96 2 | not wasActive -> do -- inactive
106 2 | not wasActive -> do -- inactive
97 onTimeout `E.catch` ignoreAll
107 onTimeout `E.catch` ignoreAll
@@ -99,6 +109,14 @@ initialize timeout = mkReaper defaultReaperSettings
99 4 -> return Nothing -- canceled
109 4 -> return Nothing -- canceled
100 _ -> return $ Just m
110 _ -> return $ Just m
101
111
112+#if !USE_ATOMIC_PRIMOPS
113+casCounter :: IORef Int -> Int -> Int -> IO (Bool, Int)
114+casCounter ref old new = atomicModifyIORef' ref $ \curr ->
115+ if old == curr
116+ then (new, (True, new))
117+ else (old, (False, old))
118+#endif
119+
102----------------------------------------------------------------
120----------------------------------------------------------------
103
121
104-- | Stopping timeout manager.
122-- | Stopping timeout manager.
@@ -115,7 +133,11 @@ ignoreAll _ = return ()
115-- | Registering a timeout action.
133-- | Registering a timeout action.
116register :: Manager -> TimeoutAction -> IO Handle
134register :: Manager -> TimeoutAction -> IO Handle
117register mgr onTimeout = do
135register mgr onTimeout = do
136+#if USE_ATOMIC_PRIMOPS
118 iactive <- C.newCounter 1
137 iactive <- C.newCounter 1
138+#else
139+ iactive <- newIORef 1
140+#endif
119 let h = Handle onTimeout iactive
141 let h = Handle onTimeout iactive
120 reaperAdd mgr h
142 reaperAdd mgr h
121 return h
143 return h
@@ -149,20 +171,28 @@ mkWeakThreadId t@(ThreadId t#) = IO $ \s ->
149
171
150----------------------------------------------------------------
172----------------------------------------------------------------
151
173
174+writeCounter :: Int -> Handle -> IO ()
175+#if USE_ATOMIC_PRIMOPS
176+writeCounter i (Handle _ iactive) = C.writeCounter iactive i
177+#else
178+writeCounter i (Handle _ iactive) = writeIORef iactive i
179+#endif
180+{-# INLINE writeCounter #-}
181+
152-- | Setting the state to active.
182-- | Setting the state to active.
153-- 'Manager' turns active to inactive repeatedly.
183-- 'Manager' turns active to inactive repeatedly.
154tickle :: Handle -> IO ()
184tickle :: Handle -> IO ()
155−tickle (Handle _ iactive) = C.writeCounter iactive 1
185+tickle = writeCounter 1
156
186
157-- | Setting the state to canceled.
187-- | Setting the state to canceled.
158-- 'Manager' eventually removes this without timeout action.
188-- 'Manager' eventually removes this without timeout action.
159cancel :: Handle -> IO ()
189cancel :: Handle -> IO ()
160−cancel (Handle _ iactive) = C.writeCounter iactive 4
190+cancel = writeCounter 4
161
191
162-- | Setting the state to paused.
192-- | Setting the state to paused.
163-- 'Manager' does not change the value.
193-- 'Manager' does not change the value.
164pause :: Handle -> IO ()
194pause :: Handle -> IO ()
165−pause (Handle _ iactive) = C.writeCounter iactive 3
195+pause = writeCounter 3
166
196
167-- | Setting the paused state to active.
197-- | Setting the paused state to active.
168-- This is an alias to 'tickle'.
198-- This is an alias to 'tickle'.
warp/warp.cabal+9−3
@@ -1,5 +1,5 @@
1Name: warp
1Name: warp
2−Version: 3.0.2.1
2+Version: 3.0.2.2
3Synopsis: A fast, light-weight web server for WAI applications.
3Synopsis: A fast, light-weight web server for WAI applications.
4License: MIT
4License: MIT
5License-file: LICENSE
5License-file: LICENSE
@@ -52,7 +52,10 @@ Library
52 , wai >= 3.0 && < 3.1
52 , wai >= 3.0 && < 3.1
53 , text
53 , text
54 , streaming-commons >= 0.1.2
54 , streaming-commons >= 0.1.2
55+
56+ if impl(ghc >= 7.8)
55− , atomic-primops >= 0.6
57+ Build-Depends: atomic-primops >= 0.6
58+ cpp-options: -DUSE_ATOMIC_PRIMOPS
56 if flag(network-bytestring)
59 if flag(network-bytestring)
57 Build-Depends: network >= 2.2.1.5 && < 2.2.3
60 Build-Depends: network >= 2.2.1.5 && < 2.2.3
58 , network-bytestring >= 0.1.3 && < 0.1.4
61 , network-bytestring >= 0.1.3 && < 0.1.4
@@ -144,7 +147,10 @@ Test-Suite spec
144 , text
147 , text
145 , streaming-commons >= 0.1.1
148 , streaming-commons >= 0.1.1
146 , async
149 , async
150+
151+ if impl(ghc >= 7.8)
147− , atomic-primops
152+ Build-Depends: atomic-primops >= 0.6
153+ cpp-options: -DUSE_ATOMIC_PRIMOPS
148
154
149 if (os(linux) || os(freebsd) || os(darwin)) && flag(allow-sendfilefd)
155 if (os(linux) || os(freebsd) || os(darwin)) && flag(allow-sendfilefd)
150 Cpp-Options: -DSENDFILEFD
156 Cpp-Options: -DSENDFILEFD