@@ -17,13 +17,9 @@ module Effectful.Internal.Unlift
1717 , concUnlift
1818 , ephemeralConcUnlift
1919 , persistentConcUnlift
20−
21− -- * Unlifting errors
22− , UnliftError(..)
2320 ) where
2421
2522import Control.Concurrent
26−import Control.Exception
2723import Control.Monad
2824import GHC.Conc.Sync (ThreadId(..))
2925import GHC.Exts (mkWeak#, mkWeakNoFinalizer#)
@@ -96,10 +92,6 @@ data Limit
9692-- Unlift functions
9793
9894-- | Sequential unlift.
99−--
100−-- Exceptions thrown by this function:
101−--
102−-- - 'InvalidUseOfSeqUnlift' if the unlift function is used in another thread.
10395seqUnlift
10496 :: HasCallStack
10597 => ((forall r. m r -> IO r) -> IO a)
@@ -112,7 +104,9 @@ seqUnlift k es unEff = do
112104 tid <- myThreadId
113105 if tid `eqThreadId` tid0
114106 then unEff m es
115− else throwIO InvalidUseOfSeqUnlift
107+ else error
108+ $ "If you want to use the unlifting function to run Eff operations "
109+ ++ "in multiple threads, have a look at UnliftStrategy (ConcUnlift)."
116110
117111-- | Concurrent unlift for various strategies and limits.
118112concUnlift
@@ -134,11 +128,6 @@ concUnlift Persistent Unlimited k =
134128
135129-- | Concurrent unlift that doesn't preserve the environment between calls to
136130-- the unlifting function in threads other than its creator.
137−--
138−-- Exceptions thrown by this function:
139−--
140−-- - 'InvalidNumberOfUses' if the number of uses is less or equal zero.
141−-- - 'ExceededNumberOfUses' if the unlift function is called too often.
142131ephemeralConcUnlift
143132 :: HasCallStack
144133 => Int
@@ -149,7 +138,7 @@ ephemeralConcUnlift
149138 -> IO a
150139ephemeralConcUnlift uses k es0 unEff = do
151140 unless (uses > 0) $ do
152− throwIO $ InvalidNumberOfUses uses
141+ error $ "Invalid number of uses: " ++ show uses
153142 tid0 <- myThreadId
154143 -- Create a copy of the environment as a template for the other threads to
155144 -- use. This can't be done from inside the callback as the environment might
@@ -160,7 +149,10 @@ ephemeralConcUnlift uses k es0 unEff = do
160149 es <- myThreadId >>= \case
161150 tid | tid0 `eqThreadId` tid -> pure es0
162151 _ -> modifyMVar mvUses $ \case
163− 0 -> throwIO $ ExceededNumberOfUses uses
152+ 0 -> error
153+ $ "Number of permitted calls (" ++ show uses ++ ") to the unlifting "
154+ ++ "function in other threads was exceeded. Please increase the limit "
155+ ++ "or use the unlimited variant."
164156 1 -> pure (0, esTemplate)
165157 n -> do
166158 let newUses = n - 1
@@ -170,12 +162,6 @@ ephemeralConcUnlift uses k es0 unEff = do
170162
171163-- | Concurrent unlift that preserves the environment between calls to the
172164-- unlifting function within a particular thread.
173−--
174−-- Exceptions thrown by this function:
175−--
176−-- - 'InvalidNumberOfThreads' if the number of threads is less or equal zero.
177−-- - 'ExceededNumberOfThreads' if the unlift function is called by too many
178−-- threads.
179165persistentConcUnlift
180166 :: HasCallStack
181167 => Bool
@@ -187,7 +173,7 @@ persistentConcUnlift
187173 -> IO a
188174persistentConcUnlift cleanUp threads k es0 unEff = do
189175 unless (threads > 0) $ do
190− throwIO $ InvalidNumberOfThreads threads
176+ error $ "Invalid number of threads: " ++ show threads
191177 tid0 <- myThreadId
192178 -- Create a copy of the environment as a template for the other threads to
193179 -- use. This can't be done from inside the callback as the environment might
@@ -205,7 +191,10 @@ persistentConcUnlift cleanUp threads k es0 unEff = do
205191 case mes of
206192 Just es -> pure (te, es)
207193 Nothing -> case teCapacity te of
208− 0 -> throwIO $ ExceededNumberOfThreads threads
194+ 0 -> error
195+ $ "Number of other threads (" ++ show threads ++ ") permitted to "
196+ ++ "use the unlifting function was exceeded. Please increase the "
197+ ++ "limit or use the unlimited variant."
209198 1 -> do
210199 wkTidEs <- mkWeakThreadIdEnv tid esTemplate wkTid i mvEntries cleanUp
211200 let newEntries = ThreadEntries
@@ -223,38 +212,6 @@ persistentConcUnlift cleanUp threads k es0 unEff = do
223212 newEntries `seq` pure (newEntries, es)
224213 unEff m es
225214
226−----------------------------------------
227−-- Errors
228−
229−-- | An type used for errors occuring in unlifting functions.
230−--
231−-- Use the 'displayException' method of the 'Exception' type class to get
232−-- descriptive error messages.
233−data UnliftError
234− = InvalidNumberOfThreads !Int
235− | InvalidNumberOfUses !Int
236− | InvalidUseOfSeqUnlift
237− | ExceededNumberOfThreads !Int
238− | ExceededNumberOfUses !Int
239− deriving (Eq, Generic, Show)
240−
241−instance Exception UnliftError where
242− displayException (InvalidNumberOfThreads threads) =
243− "Invalid number of threads: " ++ show threads
244− displayException (InvalidNumberOfUses uses) =
245− "Invalid number of uses: " ++ show uses
246− displayException (ExceededNumberOfThreads threads) =
247− "Number of other threads (" ++ show threads ++ ") permitted to use the " ++
248− "unlifting function was exceeded. Please increase the limit or use the " ++
249− "unlimited variant."
250− displayException (ExceededNumberOfUses uses) =
251− "Number of permitted calls (" ++ show uses ++ ") to the unlifting " ++
252− "function in other threads was exceeded. Please increase the limit or " ++
253− "use the unlimited variant."
254− displayException InvalidUseOfSeqUnlift =
255− "If you want to use the unlifting function to run Eff operations in " ++
256− "multiple threads, have a look at UnliftStrategy (ConcUnlift)."
257−
258215----------------------------------------
259216-- Data types
260217