@@ -59,7 +59,12 @@ import GHC.Weak (Weak (..))
5959import System.Mem.Weak (deRefWeak)
6060import Data.Typeable (Typeable)
6161import Control.Reaper
62+#if USE_ATOMIC_PRIMOPS
6263import 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
6368
6469----------------------------------------------------------------
6570
@@ -70,7 +75,12 @@ type Manager = Reaper [Handle] Handle
7075type TimeoutAction = IO ()
7176
7277-- | 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
7484
7585-- Four states for the AtomicCounter:
7686--
@@ -91,7 +101,7 @@ initialize timeout = mkReaper defaultReaperSettings
91101 where
92102 prune m@(Handle onTimeout iactive) = do
93103 -- Try to change from active to inactive
94− (wasActive, newState) <- C.casCounter iactive 1 2
104+ (wasActive, newState) <- casCounter iactive 1 2
95105 case newState of
96106 2 | not wasActive -> do -- inactive
97107 onTimeout `E.catch` ignoreAll
@@ -99,6 +109,14 @@ initialize timeout = mkReaper defaultReaperSettings
99109 4 -> return Nothing -- canceled
100110 _ -> return $ Just m
101111
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+
102120----------------------------------------------------------------
103121
104122-- | Stopping timeout manager.
@@ -115,7 +133,11 @@ ignoreAll _ = return ()
115133-- | Registering a timeout action.
116134register :: Manager -> TimeoutAction -> IO Handle
117135register mgr onTimeout = do
136+#if USE_ATOMIC_PRIMOPS
118137 iactive <- C.newCounter 1
138+#else
139+ iactive <- newIORef 1
140+#endif
119141 let h = Handle onTimeout iactive
120142 reaperAdd mgr h
121143 return h
@@ -149,20 +171,28 @@ mkWeakThreadId t@(ThreadId t#) = IO $ \s ->
149171
150172----------------------------------------------------------------
151173
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+
152182-- | Setting the state to active.
153183-- 'Manager' turns active to inactive repeatedly.
154184tickle :: Handle -> IO ()
155−tickle (Handle _ iactive) = C.writeCounter iactive 1
185+tickle = writeCounter 1
156186
157187-- | Setting the state to canceled.
158188-- 'Manager' eventually removes this without timeout action.
159189cancel :: Handle -> IO ()
160−cancel (Handle _ iactive) = C.writeCounter iactive 4
190+cancel = writeCounter 4
161191
162192-- | Setting the state to paused.
163193-- 'Manager' does not change the value.
164194pause :: Handle -> IO ()
165−pause (Handle _ iactive) = C.writeCounter iactive 3
195+pause = writeCounter 3
166196
167197-- | Setting the paused state to active.
168198-- This is an alias to 'tickle'.