Elegant threaded `foreach`

I have two methods of a function thermo!

function thermo!(cell::FEMCell, mix::Mixture)
    # do something with `cell`
    return nothing  # note, I don't need to collect return value
end

thermo!(problem::Problem) =
    foreach(cell -> thermo!(cell, problem.mixture), getcells(problem))

The second method item-independently applies the first to a Vector{FEMCell}. I want a parallel version of thermo!(problem::Problem) using threads. (As my laptop has 2 physical cores.)

My synchronization pattern is

  1. Run using threads thermo!(problem::Problem);
  2. Wait until parallel thermo!(problem::Problem) ends;
  3. Go further…

I found Threads.@threads macro and use it as a solution

function thermo!(problem::ExplicitDarcy)
    Threads.@threads for cell in getcells(problem)
        thermo!(cell, problem.mixture)
    end
    return nothing
end

But,

Is there a more elegant solution? (As I have more similar situations in my program.)

Something like

thermo!(problem::Problem) =
    Threads.@threaded_foreach foreach(cell -> thermo!(cell, problem.mixture), getcells(problem))

UPD
I’m accidently missed Base.Threads.foreach. If it’s the solution, how to use Channel in my situation?

using ThreadsX

ThreadsX.foreach
1 Like

Thank you, @jling. The package ThreadsX seems deeper than Base.Threads, but in my project I want to avoid third-party tools.


As a solution, I defined

tforeach(f, c) = (Threads.@threads for x in c; f(x); end; return nothing)

Which I found handy as the only I need is to replace foreach with tforeach in my source file.