diff --git a/base/task.jl b/base/task.jl index 1d9e238ddef11..8c9516fb39766 100644 --- a/base/task.jl +++ b/base/task.jl @@ -131,10 +131,21 @@ const task_state_runnable = UInt8(0) const task_state_done = UInt8(1) const task_state_failed = UInt8(2) +const _state_index = findfirst(==(:_state), fieldnames(Task)) +@eval function load_state_acquire(t) + # TODO: Replace this by proper atomic operations when available + @GC.preserve t llvmcall($(""" + %ptr = inttoptr i$(Sys.WORD_SIZE) %0 to i8* + %rv = load atomic i8, i8* %ptr acquire, align 8 + ret i8 %rv + """), UInt8, Tuple{Ptr{UInt8}}, + Ptr{UInt8}(pointer_from_objref(t) + fieldoffset(Task, _state_index))) +end + @inline function getproperty(t::Task, field::Symbol) if field === :state # TODO: this field name should be deprecated in 2.0 - st = getfield(t, :_state) + st = load_state_acquire(t) if st === task_state_runnable return :runnable elseif st === task_state_done @@ -177,7 +188,7 @@ julia> istaskdone(b) true ``` """ -istaskdone(t::Task) = t._state !== task_state_runnable +istaskdone(t::Task) = load_state_acquire(t) !== task_state_runnable """ istaskstarted(t::Task) -> Bool @@ -221,7 +232,7 @@ true !!! compat "Julia 1.3" This function requires at least Julia 1.3. """ -istaskfailed(t::Task) = (t._state === task_state_failed) +istaskfailed(t::Task) = (load_state_acquire(t) === task_state_failed) Threads.threadid(t::Task) = Int(ccall(:jl_get_task_tid, Int16, (Any,), t)+1)