diff --git a/Project.toml b/Project.toml index e12dcdd..7382c08 100644 --- a/Project.toml +++ b/Project.toml @@ -25,7 +25,7 @@ PolyesterWeave = "0.1" Requires = "1" Static = "0.3.3, 0.4" StrideArraysCore = "0.2.1" -ThreadingUtilities = "0.4.5" +ThreadingUtilities = "0.5" julia = "1.5" [extras] diff --git a/src/batch.jl b/src/batch.jl index be89de8..4cf9fcb 100644 --- a/src/batch.jl +++ b/src/batch.jl @@ -1,7 +1,7 @@ -struct BatchClosure{F, A, B, C} # B is a Val{Bool} triggering free_local_threads!; C is a Val{Bool} triggering local storage +struct BatchClosure{F, A, C} # C is a Val{Bool} triggering local storage f::F end -function (b::BatchClosure{F,A,B,C})(p::Ptr{UInt}) where {F,A,B,C} +function (b::BatchClosure{F,A,C})(p::Ptr{UInt}) where {F,A,C} (offset, args) = ThreadingUtilities.load(p, A, 2*sizeof(UInt)) (offset, start) = ThreadingUtilities.load(p, UInt, offset) (offset, stop ) = ThreadingUtilities.load(p, UInt, offset) @@ -11,12 +11,11 @@ function (b::BatchClosure{F,A,B,C})(p::Ptr{UInt}) where {F,A,B,C} else b.f(args, (start+one(UInt))%Int, stop%Int) end - # B && free_local_threads!() nothing end -@inline function batch_closure(f::F, args::A, ::Val{B}, ::Val{C}) where {F,A,B, C} - bc = BatchClosure{F,A,B,C}(f) +@inline function batch_closure(f::F, args::A, ::Val{C}) where {F,A,C} + bc = BatchClosure{F,A,C}(f) @cfunction($bc, Cvoid, (Ptr{UInt},)) end @@ -71,7 +70,7 @@ end @generated function _batch_no_reserve( f!::F, threadmask_tuple::NTuple{N}, nthread_tuple, torelease_tuple, Nr, Nd, ulen, args::Vararg{Any,K}; threadlocal::Val{thread_local}=Val(false) ) where {F,K,N,thread_local} - q = quote + q::Expr = quote $(Expr(:meta,:inline)) # threads = UnsignedIteratorEarlyStop(threadmask, nthread) # threads_tuple = map(UnsignedIteratorEarlyStop, threadmask_tuple, nthread_tuple) @@ -129,7 +128,7 @@ end for k ∈ 1:K add_var!(q, argt, gcpr, args[k], :args, :gcp, k) end - push!(q.args, :(arguments = $argt), :(argtup = Reference(arguments)), :(cfunc = batch_closure(f!, argtup, Val{false}(), Val{$thread_local}())), gcpr) + push!(q.args, :(arguments = $argt), :(argtup = Reference(arguments)), :(cfunc = batch_closure(f!, argtup, Val{$thread_local}())), gcpr) push!(q.args, nothing) q end diff --git a/src/spawn.jl b/src/spawn.jl new file mode 100644 index 0000000..b39e63d --- /dev/null +++ b/src/spawn.jl @@ -0,0 +1,101 @@ +struct SpawnClosure{F, A} +end +function (b::SpawnClosure{F,A})(p::Ptr{UInt}) where {F,A} + (_, args) = ThreadingUtilities.load(p, A, 2*sizeof(UInt)) + F.instance(args...) + nothing +end +# task pointers contain... +# state, fptr, misc... +# fptr = unsafe_load(ptr, 2) +# fptr(ptr) + +@inline function setup_spawn!(p::Ptr{UInt}, fptr::Ptr{Cvoid}, argtup) + offset = ThreadingUtilities.store!(p, fptr, sizeof(UInt)) + offset = ThreadingUtilities.store!(p, argtup, offset) + nothing +end + +@generated function spawn_closure(::F, args::A) where {F,A} + :(@cfunction($(F.instance), Cvoid, (Ptr{UInt},))) +end + +""" + @spawnf t foo + +```julia +t = Polyester.request_threads(7) +t = Polyester.@spawnf t foo1(...) +t = Polyester.@spawnf t foo2(...) +t = Polyester.@spawnf t foo3(...) +t = Polyester.@spawnf t foo4(...) +t = Polyester.@spawnf t foo5(...) +t = Polyester.@spawnf t foo6(...) +t = Polyester.@spawnf t foo7(...) +foo8(...) +wait(t) + +""" +macro spawnf(tex, ex) + @assert tex isa Symbol + f = GlobalRef(__module__, ex.args[1]) + args = @view(ex.args[2:end]) + Nargs = length(args) + argtup = Expr(:tuple); resize!(argtup.args, Nargs) + for i in 1:Nargs + argtup.args[i] = args[i] + end + argsgs = gensym(:args) + fptrgs = gensym(:fptr) + tgs = gensym(:t) + tid = gensym(:tid) + q = quote + # p is the taskpointer + $argsgs = $argtup + $fptrgs = $spawn_closure($f, $argsgs) + $tid, $tgs = $popfirst($tex) + $(ThreadingUtilities.launch)($tid, $fptrgs, $argsgs) do p, fptr, argtup + $setup_spawn!(p, fptr, argtup) + end + $tgs + end + esc(q) +end + + +#= +""" + @spawnf foo + +```julia +t = Polyester.@spawnf foo(...) +# run more code here +# later, to synchronize and free the thread +Polyester.wait(t) + +If you would like to get a result of type `T`, write +`foo!(::Base.RefValue{T}, args...) +and then +```julia +r = Ref{T}() +t = @spawn foo!(r, args...) +# run code +Polyester.wait(t) +``` +""" +macro spawnf(ex) + f = ex.args[1] + args = @view(ex.args[2:end]) + Nargs = length(args) + argtup = Expr(:tuple); resize!(argtup.args, Nargs) + for i in 1:Nargs + argtup.args[i] = args[i] + end + closure = gensym(:closure) + + quote + + end + +end +=#