|
1 | 1 | # DTask-level cancellation
|
2 | 2 |
|
3 |
| -struct CancelToken |
4 |
| - cancelled::Base.RefValue{Bool} |
| 3 | +mutable struct CancelToken |
| 4 | + @atomic cancelled::Bool |
| 5 | + @atomic graceful::Bool |
5 | 6 | event::Base.Event
|
6 | 7 | end
|
7 |
| -CancelToken() = CancelToken(Ref(false), Base.Event()) |
8 |
| -function cancel!(token::CancelToken) |
9 |
| - token.cancelled[] = true |
| 8 | +CancelToken() = CancelToken(false, false, Base.Event()) |
| 9 | +function cancel!(token::CancelToken; graceful::Bool=true) |
| 10 | + if !graceful |
| 11 | + @atomic token.graceful = false |
| 12 | + end |
| 13 | + @atomic token.cancelled = true |
10 | 14 | notify(token.event)
|
11 | 15 | return
|
12 | 16 | end
|
13 |
| -is_cancelled(token::CancelToken) = token.cancelled[] |
| 17 | +function is_cancelled(token::CancelToken; must_force::Bool=false) |
| 18 | + if token.cancelled[] |
| 19 | + if must_force && token.graceful[] |
| 20 | + # If we're only responding to forced cancellation, ignore graceful cancellations |
| 21 | + return false |
| 22 | + end |
| 23 | + return true |
| 24 | + end |
| 25 | + return false |
| 26 | +end |
14 | 27 | Base.wait(token::CancelToken) = wait(token.event)
|
15 | 28 | # TODO: Enable this for safety
|
16 | 29 | #Serialization.serialize(io::AbstractSerializer, ::CancelToken) =
|
@@ -128,7 +141,7 @@ function _cancel!(state, tid, force, halt_sch)
|
128 | 141 | push!(istate.cancelled, tid)
|
129 | 142 | to_proc = istate.proc
|
130 | 143 | put!(istate.return_queue, (myid(), to_proc, tid, (InterruptException(), nothing)))
|
131 |
| - cancel!(istate.cancel_tokens[tid]) |
| 144 | + cancel!(istate.cancel_tokens[tid]; graceful=false) |
132 | 145 | end
|
133 | 146 | end
|
134 | 147 | end
|
|
0 commit comments