Skip to content

Commit 51e76de

Browse files
committed
Add macro mt_out_of_order
1 parent 0deb6bb commit 51e76de

File tree

4 files changed

+74
-0
lines changed

4 files changed

+74
-0
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.4.1"
44

55
[deps]
66
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
7+
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
78

89
[compat]
910
julia = "1"

src/ParallelProcessingTools.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ module ParallelProcessingTools
77
using Base.Threads
88
using Distributed
99

10+
using MacroTools
11+
1012
include("threadsafe.jl")
1113
include("threadlocal.jl")
1214
include("onthreads.jl")

src/onthreads.jl

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,57 @@ macro mt_async(expr)
223223
end
224224
end
225225
export @mt_async
226+
227+
228+
using MacroTools
229+
"""
230+
@mt_out_of_order begin expr... end
231+
232+
Runs all top-level expressions in `begin expr... end` on parallel tasks.
233+
On Julia >= v1.3, the tasks will run multi-threaded.
234+
235+
Example:
236+
237+
```
238+
@mt_out_of_order begin
239+
a = foo()
240+
bar()
241+
c = baz()
242+
end
243+
244+
will run `a = foo()`, `bar()` and `c = baz()` in parallel and in arbitrary
245+
order, results of assignments will appear in the outside scope.
246+
"""
247+
macro mt_out_of_order(ex)
248+
if !(ex isa Expr && ex.head == :block)
249+
throw(ErrorException("@mt_out_of_order expects a code block as it's argument"))
250+
end
251+
252+
exprs = ex.args
253+
idxs = eachindex(ex.args)
254+
tasks = gensym(:tasks)
255+
handle_results = Vector{Expr}()
256+
for i in idxs
257+
trg = nothing; val = nothing;
258+
if @capture(exprs[i], trg_ = val_)
259+
if val isa Expr
260+
exprs[i] = :(push!($tasks, @mt_async($(esc(val)))))
261+
push!(handle_results, :($(esc(trg)) = fetch(popfirst!($tasks))))
262+
else
263+
exprs[i] = esc(exprs[i])
264+
end
265+
elseif exprs[i] isa Expr
266+
ftvar = gensym()
267+
exprs[i] = :(push!($tasks, @mt_async($(esc(exprs[i])))))
268+
push!(handle_results, :(wait(popfirst!($tasks))))
269+
else
270+
exprs[i] = esc(exprs[i])
271+
end
272+
end
273+
pushfirst!(exprs, :($tasks = Vector{Task}()))
274+
append!(exprs, handle_results)
275+
push!(exprs, :(@assert isempty($tasks)))
276+
push!(exprs, :nothing)
277+
ex
278+
end
279+
export @mt_out_of_order

test/test_onthreads.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,23 @@ using Base.Threads
4949
end
5050
end
5151

52+
@testset "macro mt_out_of_order" begin
53+
@test begin
54+
b = 0
55+
foo() = b = 9
56+
bar() = 33
57+
58+
@mt_out_of_order begin
59+
a = (sleep(0.05); 42)
60+
foo()
61+
c::Int = bar()
62+
63+
d = :trivial
64+
end
65+
(a, b, c, d) == (42, 9, 33, :trivial)
66+
end
67+
end
68+
5269
@testset "Examples" begin
5370
@testset "Example 1" begin
5471
tlsum = ThreadLocal(0.0)

0 commit comments

Comments
 (0)