Condition to use or not to use threaded for loop

@inbounds Threads.@threads

This won’t work.
Threads.@threads creates a closure, which effectively “protects” everything inside from the @inbounds.

You should do something more like

Threads.@threads for $(esc(expr.args[1].args[1])) = $(esc(expr.args[1].args[2]))
  @inbounds begin
    $(esc(expr.args[2]))
  end
end

EDIT:
My preferred approach to macros is to esc everything, and gensym all the symbols I add manually.
Except for very simple macros, I prefer handling hygiene manually. I find it much simpler and more intuitive.

That said, for the @simd, you’re not inserting symbols of your own, so just esc the entire expression.
You can interpolate the modules if you’re worried about someone breaking your macro by defining their own @inbounds and @simd in the scope they’re trying to use @usethreads:

julia> macro usethreads(cond::Bool, expr)
           @assert expr.head == :for
           if cond
               quote
                   Threads.@threads for $(esc(expr.args[1].args[1])) = $(esc(expr.args[1].args[2]))
                       @inbounds begin
                           $(esc(expr.args[2]))
                       end
                   end
               end
           else
               quote
                   $Base.@inbounds $Base.@simd for $(expr.args[1].args[1]) = $(expr.args[1].args[2])
                       $(expr.args[2])
                   end
               end |> esc
           end
       end
@usethreads (macro with 1 method)

julia> @usethreads false for i = 1:3
           println(Threads.threadid())
       end
1
1
1
1 Like