@@ -3,10 +3,18 @@ package ox
3
3
import java .util .concurrent .atomic .AtomicInteger
4
4
import java .util .concurrent .{CompletableFuture , ConcurrentHashMap }
5
5
import scala .reflect .ClassTag
6
+ import scala .util .NotGiven
7
+ import scala .util .boundary .Label
6
8
7
9
sealed abstract class Supervised
8
10
object SupervisedEvidence extends Supervised
9
11
12
+ private inline def availableInScope [A ]: Boolean =
13
+ compiletime.summonFrom {
14
+ case _ : NotGiven [A ] => false
15
+ case _ : A => true
16
+ }
17
+
10
18
/** Starts a new concurrency scope, which allows starting forks in the given code block `f`. Forks can be started using [[fork ]],
11
19
* [[forkUser ]], [[forkCancellable ]] and [[forkUnsupervised ]]. All forks are guaranteed to complete before this scope completes.
12
20
*
@@ -27,7 +35,19 @@ object SupervisedEvidence extends Supervised
27
35
* @see
28
36
* [[supervisedError ]] Starts a scope in supervised mode, with the additional ability to report application errors
29
37
*/
30
- def supervised [T ](f : Supervised ?=> Ox ?=> T ): T = supervisedError(NoErrorMode )(f)
38
+ inline def supervised [T ](f : Supervised ?=> Ox ?=> T ): T =
39
+ inline if availableInScope[Label [Either [Nothing , Nothing ]]] && availableInScope[Forked ] then
40
+ compiletime.error(
41
+ " Nesting supervised scopes along with fork and either blocks is disallowed to prevent unsafe .ok() combinator usage on forks."
42
+ )
43
+ else supervisedErrorInternal(NoErrorMode )(f)
44
+
45
+ inline def supervisedError [E , F [_], T ](em : ErrorMode [E , F ])(f : Supervised ?=> OxError [E , F ] ?=> F [T ]): F [T ] =
46
+ inline if availableInScope[Label [Either [Nothing , Nothing ]]] && availableInScope[Forked ] then
47
+ compiletime.error(
48
+ " Nesting supervised scopes along with fork and either blocks is disallowed to prevent unsafe .ok() combinator usage on forks."
49
+ )
50
+ else supervisedErrorInternal(em)(f)
31
51
32
52
/** Starts a new concurrency scope, which allows starting forks in the given code block `f`. Forks can be started using [[fork ]],
33
53
* [[forkError ]], [[forkUser ]], [[forkUserError ]], [[forkCancellable ]] and [[forkUnsupervised ]]. All forks are guaranteed to complete
@@ -39,7 +59,7 @@ def supervised[T](f: Supervised ?=> Ox ?=> T): T = supervisedError(NoErrorMode)(
39
59
* @see
40
60
* [[forkError ]] On details how to use application errors.
41
61
*/
42
- def supervisedError [E , F [_], T ](em : ErrorMode [E , F ])(f : Supervised ?=> OxError [E , F ] ?=> F [T ]): F [T ] =
62
+ def supervisedErrorInternal [E , F [_], T ](em : ErrorMode [E , F ])(f : Supervised ?=> OxError [E , F ] ?=> F [T ]): F [T ] =
43
63
val s = DefaultSupervisor [E ]
44
64
val capability = OxError (s, em)
45
65
try
0 commit comments